Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update org URL scheme from <id-slug> to <slug> #334

Merged
merged 3 commits into from
Sep 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions dmoj/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,9 @@ def paged_list_view(view, name):

path('organizations/', organization.OrganizationList.as_view(), name='organization_list'),
path('organizations/create', organization.CreateOrganization.as_view(), name='organization_create'),
path('organization/<int:pk>-<slug:slug>', include([
path('organization/<int:pk>-<path:suffix>',
lambda _, pk, suffix: HttpResponsePermanentRedirect('/organization/%s' % suffix)),
path('organization/<slug:slug>', include([
path('', organization.OrganizationHome.as_view(), name='organization_home'),
path('/users/', organization.OrganizationUsers.as_view(), name='organization_users'),
path('/join', organization.JoinOrganization.as_view(), name='join_organization'),
Expand Down Expand Up @@ -305,7 +307,7 @@ def paged_list_view(view, name):
path('new', organization.BlogPostCreateOrganization.as_view(), name='blog_post_create_organization'),
])),

path('/', lambda _, pk, slug: HttpResponsePermanentRedirect(reverse('organization_home', args=[pk, slug]))),
path('/', lambda _, slug: HttpResponsePermanentRedirect(reverse('organization_home', args=[slug]))),
])),

path('runtimes/', language.LanguageList.as_view(), name='runtime_list'),
Expand Down
19 changes: 19 additions & 0 deletions judge/migrations/0197_org_slugs_begin_with_letter.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Generated by Django 3.2.20 on 2023-09-26 16:45

import django.core.validators
from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('judge', '0196_view_all_user_comment_permission'),
]

operations = [
migrations.AlterField(
model_name='organization',
name='slug',
field=models.SlugField(help_text='Organization name shown in URLs.', max_length=128, unique=True, validators=[django.core.validators.RegexValidator('^[a-zA-Z]', 'Organization slugs must begin with a letter.')], verbose_name='organization slug'),
),
]
6 changes: 4 additions & 2 deletions judge/models/profile.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ class Organization(models.Model):
name = models.CharField(max_length=128, verbose_name=_('organization title'))
slug = models.SlugField(max_length=128, verbose_name=_('organization slug'),
help_text=_('Organization name shown in URLs.'),
validators=[RegexValidator(r'^[a-zA-Z]',
_('Organization slugs must begin with a letter.'))],
unique=True)
short_name = models.CharField(max_length=20, verbose_name=_('short name'),
help_text=_('Displayed beside user name during contests.'))
Expand Down Expand Up @@ -103,10 +105,10 @@ def __str__(self):
return self.name

def get_absolute_url(self):
return reverse('organization_home', args=(self.id, self.slug))
return reverse('organization_home', args=[self.slug])

def get_users_url(self):
return reverse('organization_users', args=(self.id, self.slug))
return reverse('organization_users', args=[self.slug])

class Meta:
ordering = ['name']
Expand Down
2 changes: 1 addition & 1 deletion judge/sitemap.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ class OrganizationSitemap(Sitemap):
priority = 0.5

def items(self):
return Organization.objects.values_list('id', 'slug')
return Organization.objects.values_list('slug')

def location(self, obj):
return reverse('organization_home', args=obj)
Expand Down
24 changes: 10 additions & 14 deletions judge/views/organization.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ class BaseOrganizationListView(OrganizationMixin, ListView):
slug_url_kwarg = 'slug'

def get_object(self):
return get_object_or_404(Organization, id=self.kwargs.get('pk'))
return get_object_or_404(Organization, slug=self.kwargs.get('slug'))

def get_context_data(self, **kwargs):
return super().get_context_data(organization=self.object, **kwargs)
Expand Down Expand Up @@ -119,7 +119,7 @@ def get_context_data(self, **kwargs):
context['users'] = ranker(context['users'])
context['partial'] = True
context['is_admin'] = self.can_edit_organization()
context['kick_url'] = reverse('organization_user_kick', args=[self.object.id, self.object.slug])
context['kick_url'] = reverse('organization_user_kick', args=[self.object.slug])
context['first_page_href'] = '.'
context.update(self.get_sort_context())
context.update(self.get_sort_paginate_context())
Expand Down Expand Up @@ -174,8 +174,6 @@ class OrganizationRequestForm(Form):

class RequestJoinOrganization(LoginRequiredMixin, SingleObjectMixin, FormView):
model = Organization
slug_field = 'key'
slug_url_kwarg = 'key'
template_name = 'organization/requests/request.html'
form_class = OrganizationRequestForm

Expand All @@ -201,7 +199,7 @@ def form_valid(self, form):
request.state = 'P'
request.save()
return HttpResponseRedirect(reverse('request_organization_detail', args=(
request.organization.id, request.organization.slug, request.id,
request.organization.slug, request.id,
)))


Expand All @@ -224,8 +222,6 @@ def get_object(self, queryset=None):

class OrganizationRequestBaseView(LoginRequiredMixin, SingleObjectTemplateResponseMixin, SingleObjectMixin, View):
model = Organization
slug_field = 'key'
slug_url_kwarg = 'key'
tab = None

def get_object(self, queryset=None):
Expand Down Expand Up @@ -432,9 +428,9 @@ def get_context_data(self, **kwargs):
return context

def dispatch(self, request, *args, **kwargs):
if 'pk' not in kwargs:
raise ImproperlyConfigured('Must pass a pk')
self.organization = get_object_or_404(Organization, pk=kwargs['pk'])
if 'slug' not in kwargs:
raise ImproperlyConfigured('Must pass a slug')
self.organization = get_object_or_404(Organization, slug=kwargs['slug'])
self.object = self.organization

if not self.allow_all_users and \
Expand All @@ -456,9 +452,9 @@ def can_edit_organization(self, org=None):

class CustomAdminOrganizationMixin(CustomOrganizationMixin):
def dispatch(self, request, *args, **kwargs):
if 'pk' not in kwargs:
raise ImproperlyConfigured('Must pass a pk')
self.organization = get_object_or_404(Organization, pk=kwargs['pk'])
if 'slug' not in kwargs:
raise ImproperlyConfigured('Must pass a slug')
self.organization = get_object_or_404(Organization, slug=kwargs['slug'])
if self.can_edit_organization():
return super(CustomAdminOrganizationMixin, self).dispatch(request, *args, **kwargs)
raise PermissionDenied
Expand Down Expand Up @@ -503,7 +499,7 @@ def get_queryset(self):

def get_context_data(self, **kwargs):
context = super(OrganizationHome, self).get_context_data(**kwargs)
context['first_page_href'] = reverse('organization_home', args=[self.object.pk, self.object.slug])
context['first_page_href'] = reverse('organization_home', args=[self.object.slug])
context['title'] = self.object.name
context['can_edit'] = self.can_edit_organization()
context['is_member'] = self.request.profile in self.object
Expand Down
4 changes: 4 additions & 0 deletions locale/en/LC_MESSAGES/django.po
Original file line number Diff line number Diff line change
Expand Up @@ -2329,6 +2329,10 @@ msgstr ""
msgid "Organization name shown in URL"
msgstr ""

#: judge/models/profile.py:45
msgid "Organization slugs must begin with a letter."
msgstr ""

#: judge/models/profile.py:45
msgid "Displayed beside user name during contests"
msgstr ""
Expand Down
4 changes: 4 additions & 0 deletions locale/vi/LC_MESSAGES/django.po
Original file line number Diff line number Diff line change
Expand Up @@ -2422,6 +2422,10 @@ msgstr "tên viết tắt trên đường dẫn"
msgid "Organization name shown in URLs."
msgstr "Tên viết tắt của tổ chức, được dùng trong đường dẫn tới tổ chức"

#: judge/models/profile.py:45
msgid "Organization slugs must begin with a letter."
msgstr "Tên viết tắt của tổ chức phải bắt đầu bằng một chữ cái."

#: judge/models/profile.py:45
msgid "Displayed beside user name during contests."
msgstr "Hiển thị bên cạnh tên trong các kỳ thi"
Expand Down
12 changes: 6 additions & 6 deletions templates/organization/home.html
Original file line number Diff line number Diff line change
Expand Up @@ -89,37 +89,37 @@ <h3>{{ _('Controls') }} <i class="fa fa-question-circle"></i></h3>
<div class="sidebox-content" style="padding: 1em;">
{% if request.user.is_authenticated %}
{% if is_member %}
<form method="post" action="{{ url('leave_organization', organization.id, organization.slug) }}">
<form method="post" action="{{ url('leave_organization', organization.slug) }}">
{% csrf_token %}
<input type="submit" class="unselectable button full leave-organization" value="{{ _('Leave organization') }}">
</form>
{% elif organization.is_open %}
<form method="post" action="{{ url('join_organization', organization.id, organization.slug) }}">
<form method="post" action="{{ url('join_organization', organization.slug) }}">
{% csrf_token %}
<input type="submit" class="unselectable button full" value="{{ _('Join organization') }}">
</form>
{% else %}
<a href="{{ url('request_organization', organization.id, organization.slug) }}"
<a href="{{ url('request_organization', organization.slug) }}"
class="unselectable button full">{{ _('Request membership') }}</a>
{% endif %}
{% endif %}
<br>
{% if can_edit %}
{% if not organization.is_open %}
<div>
<a href="{{ url('organization_requests_pending', organization.id, organization.slug) }}">
<a href="{{ url('organization_requests_pending', organization.slug) }}">
{{ _('View requests') }}
{% if num_requests %}<span class="badge">{{ num_requests }}</span>{% endif %}
</a>
</div>
{% endif %}
{% if perms.judge.edit_organization_post %}
<div>
<a href="{{ url('blog_post_create_organization', organization.id, organization.slug) }}">{{ _('Create blog post') }}</a>
<a href="{{ url('blog_post_create_organization', organization.slug) }}">{{ _('Create blog post') }}</a>
</div>
{% endif %}
<div>
<a href="{{ url('edit_organization', organization.id, organization.slug) }}">{{ _('Edit organization') }}</a>
<a href="{{ url('edit_organization', organization.slug) }}">{{ _('Edit organization') }}</a>
</div>
{% endif %}
{% if perms.judge.change_organization %}
Expand Down
2 changes: 1 addition & 1 deletion templates/organization/requests/log.html
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
<tr id="request-{{ r.id }}">
<td>{{ link_user(r.user) }}</td>
<td>
<a href="{{ url('request_organization_detail', object.id, object.slug, r.id) }}">
<a href="{{ url('request_organization_detail', object.slug, r.id) }}">
{{- r.time|date(_("N j, Y, H:i")) -}}
</a>
</td>
Expand Down
4 changes: 2 additions & 2 deletions templates/organization/requests/pending.html
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
{% for form in formset %}
<tr id="request-{{ form.instance.id }}">
<td>{{ form.id }}{{ link_user(form.instance.user) }}</td>
<td><a href="{{ url('request_organization_detail', object.id, object.slug, form.instance.id) }}">
<td><a href="{{ url('request_organization_detail', object.slug, form.instance.id) }}">
{{ form.instance.time|date(_("N j, Y, H:i")) }}
</a></td>
<td>{{ form.state }}</td>
Expand All @@ -36,4 +36,4 @@
{% else %}
<p>{{ _('There are no requests to approve.') }}</p>
{% endif %}
{% endblock %}
{% endblock %}
10 changes: 5 additions & 5 deletions templates/organization/requests/tabs.html
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
<div class="tabs">
<ul>
<li{% if tab == 'pending' %} class="active"{% endif %}>
<a href="{{ url('organization_requests_pending', object.id, object.slug) }}">{{ _('Pending') }}</a>
<a href="{{ url('organization_requests_pending', object.slug) }}">{{ _('Pending') }}</a>
</li>
<li{% if tab == 'log' %} class="active"{% endif %}>
<a href="{{ url('organization_requests_log', object.id, object.slug) }}">{{ _('Log') }}</a>
<a href="{{ url('organization_requests_log', object.slug) }}">{{ _('Log') }}</a>
</li>
<li{% if tab == 'approved' %} class="active"{% endif %}>
<a href="{{ url('organization_requests_approved', object.id, object.slug) }}">{{ _('Approved') }}</a>
<a href="{{ url('organization_requests_approved', object.slug) }}">{{ _('Approved') }}</a>
</li>
<li{% if tab == 'rejected' %} class="active"{% endif %}>
<a href="{{ url('organization_requests_rejected', object.id, object.slug) }}">{{ _('Rejected') }}</a>
<a href="{{ url('organization_requests_rejected', object.slug) }}">{{ _('Rejected') }}</a>
</li>
</ul>
</div>
</div>
12 changes: 6 additions & 6 deletions templates/organization/tabs.html
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,20 @@ <h2>{{ content_title or title }}</h2>
<br>
<div class="tabs">
<ul>
{{ make_tab('home', 'fa-info-circle', url('organization_home', organization.pk, organization.slug), _('Home')) }}
{{ make_tab('home', 'fa-info-circle', url('organization_home', organization.slug), _('Home')) }}
{{ make_tab('users', 'fa-university', organization.get_users_url(), _('Users')) }}
{{ make_tab('problem-list', 'fa-puzzle-piece', url('problem_list_organization', organization.pk, organization.slug), _('Problems list')) }}
{{ make_tab('contest-list', 'fa-trophy', url('contest_list_organization', organization.pk, organization.slug), _('Contests list')) }}
{{ make_tab('submission-list', 'fa-list', url('submission_list_organization', organization.pk, organization.slug), _('Submissions')) }}
{{ make_tab('problem-list', 'fa-puzzle-piece', url('problem_list_organization', organization.slug), _('Problems list')) }}
{{ make_tab('contest-list', 'fa-trophy', url('contest_list_organization', organization.slug), _('Contests list')) }}
{{ make_tab('submission-list', 'fa-list', url('submission_list_organization', organization.slug), _('Submissions')) }}
</ul>
<span class="spacer"></span>
<ul>
{% if organization.is_admin(request.profile) %}
{% if request.user.has_perm('judge.create_organization_problem') %}
{{ make_tab('create', 'fa-plus', url('problem_create_organization', organization.id, organization.slug), _('Create new problem')) }}
{{ make_tab('create', 'fa-plus', url('problem_create_organization', organization.slug), _('Create new problem')) }}
{% endif %}
{% if request.user.has_perm('judge.create_private_contest') %}
{{ make_tab('create', 'fa-plus', url('contest_create_organization', organization.id, organization.slug), _('Create new contest')) }}
{{ make_tab('create', 'fa-plus', url('contest_create_organization', organization.slug), _('Create new contest')) }}
{% endif %}
{% endif %}
</ul>
Expand Down