From 955ecb35ed6c1cb7e2328d8d775b22d8165b66fa Mon Sep 17 00:00:00 2001 From: Lucas Brandstaetter <lucas@brandstaetter.tech> Date: Mon, 23 Dec 2024 03:14:09 +0100 Subject: [PATCH] Update assembly slug handling in plainui - Remove unused slug URL pattern - Use `slug__iexact` lookups - Use `slug_url_kwarg` and `slug_field` attributes in `AssemblyView` This is in place of a custom `dispatch` method that was used to unify the `assembly_slug` and `slug` URL patterns Fixes #665 --- src/api/serializers.py | 2 +- src/api/views/badges.py | 4 ++-- src/api/views/mixins.py | 2 +- src/backoffice/forms/__init__.py | 4 ++-- src/backoffice/forms/assemblies.py | 4 ++-- src/backoffice/views/moderation/mixins.py | 2 +- src/plainui/urls.py | 1 - src/plainui/views/assemblies.py | 7 ++----- 8 files changed, 11 insertions(+), 15 deletions(-) diff --git a/src/api/serializers.py b/src/api/serializers.py index bbad60a25..e8ff4d019 100644 --- a/src/api/serializers.py +++ b/src/api/serializers.py @@ -228,7 +228,7 @@ class BadgeSerializer(HubModelSerializer): ) def create(self, validated_data): - issuing_assembly = Assembly.objects.filter(slug=self.context['assembly']) + issuing_assembly = Assembly.objects.filter(slug__iexact=self.context['assembly']) conference = Conference.objects.filter(slug=self.context['conference']) validated_data.update({'conference': conference, 'issuing_assembly': issuing_assembly}) return super().create(validated_data) diff --git a/src/api/views/badges.py b/src/api/views/badges.py index 5d6a7d491..a9d9789ac 100644 --- a/src/api/views/badges.py +++ b/src/api/views/badges.py @@ -26,7 +26,7 @@ class BadgeListCreate(ListCreateAPIView): def get_queryset(self): queryset = self.model.objects.all() assembly = self.kwargs.get('assembly') - return queryset.filter(issuing_assembly__slug=assembly) + return queryset.filter(issuing_assembly__slug__iexact=assembly) def get_serializer_context(self): context = super().get_serializer_context() @@ -43,7 +43,7 @@ class BadgeTokenListCreate(ConferenceSlugAssemblyMixin, ListCreateAPIView): queryset = BadgeToken.objects.all() assembly = self.kwargs.get('assembly') badge = self.kwargs.get('pk') - return queryset.filter(badge=badge, badge__issuing_assembly__slug=assembly) + return queryset.filter(badge=badge, badge__issuing_assembly__slug__iexact=assembly) def get_serializer_context(self): if self.kwargs.get('pk'): diff --git a/src/api/views/mixins.py b/src/api/views/mixins.py index 46c930245..8ba7e8dee 100644 --- a/src/api/views/mixins.py +++ b/src/api/views/mixins.py @@ -54,7 +54,7 @@ class ConferenceSlugAssemblyMixin(ConferenceSlugMixin): if self._assembly is None: assembly_slug = self.request.resolver_match.kwargs['assembly'] try: - self._assembly = Assembly.objects.associated_with_user(self.conference, user=self.request.user).get(slug=assembly_slug) + self._assembly = Assembly.objects.associated_with_user(self.conference, user=self.request.user).get(slug__iexact=assembly_slug) except Assembly.DoesNotExist: if issuing_token := self.kwargs.get('issuing_token', None): try: diff --git a/src/backoffice/forms/__init__.py b/src/backoffice/forms/__init__.py index 9753d9d08..23cf9d09c 100644 --- a/src/backoffice/forms/__init__.py +++ b/src/backoffice/forms/__init__.py @@ -86,13 +86,13 @@ class ScheduleSourceCreateForm(forms.ModelForm): assembly_slug = self.cleaned_data['assembly_slug'] if assembly_slug == '*': return None - if not Assembly.objects.filter(conference=self._conference, slug=assembly_slug).exists(): + if not Assembly.objects.filter(conference=self._conference, slug__iexact=assembly_slug).exists(): raise ValidationError('An assembly with this slug does not exist.') return assembly_slug def clean(self): assembly_slug = self.cleaned_data.get('assembly_slug') - self.instance.assembly = Assembly.objects.get(conference=self._conference, slug=assembly_slug) if assembly_slug else None + self.instance.assembly = Assembly.objects.get(conference=self._conference, slug__iexact=assembly_slug) if assembly_slug else None self.instance.conference = self._conference try: self.instance.import_frequency = str2timedelta(self.cleaned_data.get('import_frequency')) diff --git a/src/backoffice/forms/assemblies.py b/src/backoffice/forms/assemblies.py index cb3d92f4d..3cc02fda6 100644 --- a/src/backoffice/forms/assemblies.py +++ b/src/backoffice/forms/assemblies.py @@ -36,7 +36,7 @@ class AssemblyCreateForm(forms.ModelForm): if self._conference.has_disclaimer('assembly') and not self.cleaned_data['disclaimer']: self.add_error('disclaimer', _('Assembly__disclaimer-needed')) - if (slug := self.cleaned_data.get('slug')) and Assembly.objects.filter(conference=self._conference, slug=slug).exists(): + if (slug := self.cleaned_data.get('slug')) and Assembly.objects.filter(conference=self._conference, slug__iexact=slug).exists(): self.add_error('slug', _('Assembly__slug__already_exists')) # ensure Assembly's conference is set before saving @@ -106,7 +106,7 @@ class AssemblyEditForm(TranslatedFieldsForm): # slug must not already exist in the conference slug = self.cleaned_data.get('slug') - if slug is not None and Assembly.objects.filter(conference=self.instance.conference, slug=slug).exclude(pk=self.instance.pk).exists(): + if slug is not None and Assembly.objects.filter(conference=self.instance.conference, slug__iexact=slug).exclude(pk=self.instance.pk).exists(): self.add_error('slug', _('Assembly__slug__already_exists')) diff --git a/src/backoffice/views/moderation/mixins.py b/src/backoffice/views/moderation/mixins.py index d912468bf..b4f75e7eb 100644 --- a/src/backoffice/views/moderation/mixins.py +++ b/src/backoffice/views/moderation/mixins.py @@ -39,7 +39,7 @@ def lookup_moderation_items(conference: Conference, query: str): candidates.append(('assembly', p.kwargs['pk'])) for kw in ['slug', 'assembly_slug']: if kw in p.kwargs: - for a in conference.assemblies.filter(slug=p.kwargs[kw]).values('pk'): + for a in conference.assemblies.filter(slug__iexact=p.kwargs[kw]).values('pk'): candidates.append(('assembly', a['pk'])) if '/event' in p.route: if 'pk' in p.kwargs: diff --git a/src/plainui/urls.py b/src/plainui/urls.py index f50098409..c6ac7b5d6 100644 --- a/src/plainui/urls.py +++ b/src/plainui/urls.py @@ -89,7 +89,6 @@ urlpatterns = [ re_path(r'^assemblies/(?P<page>[0a-z])', views.AssembliesView.as_view(), name='assemblies_paginated'), re_path(r'^assemblies/all/(?P<page>[0a-z])', views.AssembliesAllView.as_view(), name='assemblies_all_paginated'), path('assembly/<slug:assembly_slug>/', views.AssemblyView.as_view(), name='assembly'), - path('assembly/<slug:slug>/', views.AssemblyView.as_view(), name='assembly'), path('sos/', views.SosList.as_view(), name='sos'), path('so/project/<slug:slug>/', views.ProjectView.as_view(self_organized=True), name='so_project'), path('report', views.ReportContentView.as_view(), name='report_content'), diff --git a/src/plainui/views/assemblies.py b/src/plainui/views/assemblies.py index c6a27a38d..0197ef7e8 100644 --- a/src/plainui/views/assemblies.py +++ b/src/plainui/views/assemblies.py @@ -36,11 +36,8 @@ logger = logging.getLogger(__name__) class AssemblyView(ConferenceRequiredMixin, DetailView): model = Assembly template_name = 'plainui/assembly.html.j2' - - def dispatch(self, request, *args, assembly_slug: str | None = None, **kwargs): - if assembly_slug: - self.kwargs.update({'slug': self.kwargs.pop('assembly_slug')}) - return super().dispatch(request, *args, **kwargs) + slug_url_kwarg = 'assembly_slug' + slug_field = 'slug__iexact' def get_queryset(self) -> QuerySet[Any]: return Assembly.objects.conference_accessible(self.conf).prefetch_related( -- GitLab