Coverage for website/promotion/admin.py: 46.75%
67 statements
« prev ^ index » next coverage.py v7.6.7, created at 2025-08-14 10:31 +0000
« prev ^ index » next coverage.py v7.6.7, created at 2025-08-14 10:31 +0000
1"""Registers admin interfaces for the models defined in this module."""
3from django.contrib import admin
4from django.contrib.admin import ModelAdmin
5from django.db import models
6from django.db.models.functions import Lower
8from events.services import is_organiser
9from promotion.forms import PromotionRequestForm
11from .models import PromotionChannel, PromotionRequest
14class CaseInsensitiveFilter(admin.FieldListFilter):
15 def __init__(self, field, request, params, model, model_admin, field_path):
16 self.lookup_kwarg = f"{field_path}__iexact"
17 self.lookup_kwarg2 = f"{field_path}__isnull"
18 self.lookup_val = params.get(self.lookup_kwarg)
19 self.lookup_val2 = params.get(self.lookup_kwarg2)
20 super().__init__(field, request, params, model, model_admin, field_path)
21 self.empty_value_display = model_admin.get_empty_value_display()
22 queryset = model_admin.get_queryset(request)
23 lookup_choices = (
24 queryset.annotate(lowered=Lower(field.name))
25 .order_by(field.name)
26 .distinct()
27 .values_list(field.name, flat=True)
28 )
29 self.lookup_choices = set(
30 map(lambda x: x.lower() if x is not None else x, lookup_choices)
31 )
33 def get_facet_counts(self, pk_attname, filtered_qs):
34 return {
35 f"{i}__c": models.Count(
36 pk_attname,
37 filter=models.Q(
38 (self.lookup_kwarg, value)
39 if value is not None
40 else (self.lookup_kwarg2, True)
41 ),
42 )
43 for i, value in enumerate(self.lookup_choices)
44 }
46 def choices(self, changelist):
47 add_facets = changelist.add_facets
48 facet_counts = self.get_facet_queryset(changelist)
49 yield {
50 "selected": self.lookup_val is None,
51 "query_string": changelist.get_query_string(
52 remove=[self.lookup_kwarg, self.lookup_kwarg2]
53 ),
54 "display": "All",
55 }
56 include_none = False
57 empty_title = self.empty_value_display
58 for key, val in enumerate(self.lookup_choices):
59 if add_facets:
60 count = facet_counts[f"{key}__c"]
61 if val is None:
62 include_none = True
63 empty_title = f"{empty_title} ({count})" if add_facets else empty_title
64 continue
65 yield {
66 "selected": self.lookup_val is not None and val in self.lookup_val,
67 "query_string": changelist.get_query_string({self.lookup_kwarg: val}),
68 "display": f"{val} ({count})" if add_facets else val,
69 }
70 if include_none:
71 yield {
72 "selected": self.lookup_val2 is True,
73 "query_string": changelist.get_query_string(
74 {self.lookup_kwarg2: "True"}, remove=[self.lookup_kwarg]
75 ),
76 "display": empty_title,
77 }
79 def expected_parameters(self):
80 return [self.lookup_kwarg, self.lookup_kwarg2]
83@admin.register(PromotionRequest)
84class PromotionRequestAdmin(admin.ModelAdmin):
85 """This manages the admin interface for the model items."""
87 list_display = ("event", "publish_date", "channel", "assigned_to", "status")
88 list_filter = (
89 "publish_date",
90 ("assigned_to", CaseInsensitiveFilter),
91 "status",
92 )
93 date_hierarchy = "publish_date"
94 form = PromotionRequestForm
95 actions = ["mark_not_started", "mark_started", "mark_finished", "mark_published"]
97 def has_change_permission(self, request, obj=None):
98 if obj is not None and obj.event and is_organiser(request.member, obj.event): 98 ↛ 99line 98 didn't jump to line 99 because the condition on line 98 was never true
99 return True
100 return super().has_change_permission(request, obj)
102 def mark_not_started(self, request, queryset):
103 """Change the status of the event to published."""
104 self._change_published(queryset, PromotionRequest.NOT_STARTED)
106 mark_not_started.short_description = "Mark requests as not started"
108 def mark_started(self, request, queryset):
109 """Change the status of the event to published."""
110 self._change_published(queryset, PromotionRequest.STARTED)
112 mark_started.short_description = "Mark requests as started"
114 def mark_finished(self, request, queryset):
115 """Change the status of the event to published."""
116 self._change_published(queryset, PromotionRequest.FINISHED)
118 mark_finished.short_description = "Mark requests as finished"
120 def mark_published(self, request, queryset):
121 """Change the status of the event to published."""
122 self._change_published(queryset, PromotionRequest.PUBLISHED)
124 mark_published.short_description = "Mark requests as published"
126 @staticmethod
127 def _change_published(queryset, status):
128 queryset.update(status=status)
131@admin.register(PromotionChannel)
132class PromotionChannelAdmin(ModelAdmin):
133 list_display = ("name", "publisher_reminder_email")