diff --git a/AKModel/forms.py b/AKModel/forms.py index 93448b283d86d8ed75e2b1a177d5637ed0b37f6c..0701fda037c60d85f09ab328f0cc30d93b9a683b 100644 --- a/AKModel/forms.py +++ b/AKModel/forms.py @@ -177,6 +177,12 @@ class SlideExportForm(AdminIntermediateForm): initial=3, label=_("# next AKs"), help_text=_("How many next AKs should be shown on a slide?")) + types = forms.MultipleChoiceField( + label=_("AK Types"), + help_text=_("Which AK types should be included in the slides?"), + widget=forms.CheckboxSelectMultiple, + choices=AKType.objects.all().values_list('id', 'name'), + required=False) presentation_mode = forms.TypedChoiceField( initial=False, label=_("Presentation only?"), diff --git a/AKModel/models.py b/AKModel/models.py index ce33bc0b31b5b15cc7dd8c81c2e5516a8dc64968..1773af01530069f45b0152c344a1cacbb936f358 100644 --- a/AKModel/models.py +++ b/AKModel/models.py @@ -205,7 +205,7 @@ class Event(models.Model): return event def get_categories_with_aks(self, wishes_seperately=False, - filter_func=lambda ak: True, hide_empty_categories=False): + filter_func=lambda ak: True, hide_empty_categories=False, types=None): """ Get AKCategories as well as a list of AKs belonging to the category for this event @@ -213,6 +213,10 @@ class Event(models.Model): :type wishes_seperately: bool :param filter_func: Optional filter predicate, only include AK in list if filter returns True :type filter_func: (AK)->bool + :param hide_empty_categories: If True, categories with no AKs will not be included in the result + :type hide_empty_categories: bool + :param types: Optional list of AK types to filter by, if None, all types are included + :type types: list[AKType] | None :return: list of category-AK-list-tuples, optionally the additional list of AK wishes :rtype: list[(AKCategory, list[AK])] [, list[AK]] """ @@ -224,7 +228,7 @@ class Event(models.Model): # A different behavior is needed depending on whether wishes should show up inside their categories # or as a separate category - def _get_category_aks(category): + def _get_category_aks(category, types): """ Get all AKs belonging to a category Use joining and prefetching to reduce the number of necessary SQL queries @@ -233,12 +237,15 @@ class Event(models.Model): :return: QuerySet over AKs :return: QuerySet[AK] """ - return category.ak_set.select_related('event').prefetch_related('owners', 'akslot_set').all() + s = category.ak_set + if types is not None: + s = s.filter(types__in=types).distinct() + return s.select_related('event').prefetch_related('owners', 'akslot_set').all() if wishes_seperately: for category in categories: ak_list = [] - for ak in _get_category_aks(category): + for ak in _get_category_aks(category, types): if filter_func(ak): if ak.wish: ak_wishes.append(ak) @@ -250,7 +257,7 @@ class Event(models.Model): for category in categories: ak_list = [] - for ak in _get_category_aks(category): + for ak in _get_category_aks(category, types): if filter_func(ak): ak_list.append(ak) if not hide_empty_categories or len(ak_list) > 0: diff --git a/AKModel/views/manage.py b/AKModel/views/manage.py index 1a7f1930b079edc4061ac5bc0a145466640bd574..8e1e7fa426a66f775b454da38c599c26ced29970 100644 --- a/AKModel/views/manage.py +++ b/AKModel/views/manage.py @@ -16,7 +16,7 @@ from django_tex.response import PDFResponse from AKModel.forms import SlideExportForm, DefaultSlotEditorForm, JSONScheduleImportForm from AKModel.metaviews.admin import EventSlugMixin, IntermediateAdminView, IntermediateAdminActionView, AdminViewMixin -from AKModel.models import ConstraintViolation, Event, DefaultSlot, AKOwner +from AKModel.models import ConstraintViolation, Event, DefaultSlot, AKOwner, AKType class UserView(TemplateView): @@ -37,6 +37,18 @@ class ExportSlidesView(EventSlugMixin, IntermediateAdminView): title = _('Export AK Slides') form_class = SlideExportForm + def get_form(self, form_class=None): + # Filter type choices to those of the current event + # or completely hide the field if no types are specified for this event + form = super().get_form(form_class) + if self.event.aktype_set.count() > 0: + form.fields['types'].choices = [ + (ak_type.id, ak_type.name) for ak_type in self.event.aktype_set.all() + ] + else: + form.fields['types'].widget = form.fields['types'].hidden_widget() + return form + def form_valid(self, form): # pylint: disable=invalid-name template_name = 'admin/AKModel/export/slides.tex' @@ -62,10 +74,15 @@ class ExportSlidesView(EventSlugMixin, IntermediateAdminView): next_aks_list = zip_longest(*[ak_list[i + 1:] for i in range(NEXT_AK_LIST_LENGTH)], fillvalue=None) return list(zip_longest(ak_list, next_aks_list, fillvalue=[])) + # Create a list of types to filter AKs by (if at least one type was selected) + types = None + if len(form.cleaned_data['types']) > 0: + types = AKType.objects.filter(id__in=form.cleaned_data['types']) + # Get all relevant AKs (wishes separately, and either all AKs or only those who should directly or indirectly # be presented when restriction setting was chosen) categories_with_aks, ak_wishes = self.event.get_categories_with_aks(wishes_seperately=True, filter_func=lambda - ak: not RESULT_PRESENTATION_MODE or (ak.present or (ak.present is None and ak.category.present_by_default))) + ak: not RESULT_PRESENTATION_MODE or (ak.present or (ak.present is None and ak.category.present_by_default)), types=types) # Create context for LaTeX rendering context = {