Repository: tough-dev-school/education-backend

Issue:
Админка: по-умолчанию показывать только включенные промокоды
У нас накопилась огромная гора промокодов, и теперь при первом входе в админку сложно ориентироваться. Нужно сделать, чтобы по-умолчанию в админке показывались только включенные промокоды.


Discussion:

Resolving patch:
diff --git a/src/app/admin/filters.py b/src/app/admin/filters.py
--- a/src/app/admin/filters.py
+++ b/src/app/admin/filters.py
@@ -12,7 +12,7 @@ class HasClassesFilter(BooleanFilter):
             parameter_name = 'has_classes'
             def t(self, request, queryset):
                 return queryset.filter(classes__isnull=False).distinct('pk')
-            def n(self, request, queryset):
+            def f(self, request, queryset):
                 return queryset.filter(classes__isnull=True)
     """
     def lookups(self, request, model_admin):
@@ -24,8 +24,22 @@ def lookups(self, request, model_admin):
     def queryset(self, request, queryset):
         if not self.value():
             return queryset
-        else:
-            if self.value() == 't':
-                return self.t(request, queryset)
-            else:
-                return self.f(request, queryset)
+
+        if self.value() == 't':
+            return self.t(request, queryset)
+
+        return self.f(request, queryset)
+
+
+class DefaultTrueBooleanFilter(BooleanFilter):
+    def queryset(self, request, queryset):
+        if not self.value() or self.value() == 't':
+            return self.t(request, queryset)
+
+        return self.f(request, queryset)
+
+
+__all__ = [
+    'BooleanFilter',
+    'DefaultTrueBooleanFilter',
+]
diff --git a/src/orders/admin/promocodes/admin.py b/src/orders/admin/promocodes/admin.py
--- a/src/orders/admin/promocodes/admin.py
+++ b/src/orders/admin/promocodes/admin.py
@@ -1,31 +1,45 @@
-from django.urls import reverse
-from django.utils.safestring import mark_safe
 from django.utils.translation import gettext_lazy as _
 
 from app.admin import ModelAdmin, admin
+from app.admin.filters import DefaultTrueBooleanFilter
 from orders.admin.promocodes import actions
 from orders.models import PromoCode
 
 
+class PromodeActiveFilter(DefaultTrueBooleanFilter):
+    title = _('Active')
+    parameter_name = 'is_active'
+
+    def t(self, request, queryset):
+        return queryset.filter(active=True)
+
+    def f(self, request, queryset):
+        return queryset.filter(active=False)
+
+
 @admin.register(PromoCode)
 class PromoCodeAdmin(ModelAdmin):
-    list_display = [
+    list_display = (
         'id',
         'name',
-        'discount_percent',
-        'discount_value',
+        'discount',
         'order_count',
         'comment',
         'active',
-    ]
+    )
 
     list_editable = [
         'active',
     ]
 
-    list_filter = [
-        'active',
-    ]
+    list_filter = (
+        PromodeActiveFilter,
+    )
+
+    list_display_links = (
+        'id',
+        'name',
+    )
 
     actions = [actions.deactivate]
 
@@ -33,11 +47,19 @@ def get_queryset(self, request):
         return super().get_queryset(request) \
             .with_order_count()
 
-    @mark_safe
     @admin.display(description=_('Order count'), ordering='order_count')
-    def order_count(self, obj=None):
+    def order_count(self, obj: PromoCode | None = None) -> str:
         if hasattr(obj, 'order_count') and obj.order_count:
-            orders_url = reverse('admin:orders_order_changelist')
-            return f'<a href="{orders_url}?is_paid=t&promocode_id={obj.id}">{obj.order_count}</a>'
+            return str(obj.order_count)
 
         return '—'
+
+    @admin.display(description=_('Discount'), ordering='discount_percent')
+    def discount(self, obj: PromoCode | None = None) -> str:
+        if not obj:
+            return '—'
+
+        if obj.discount_value is not None:
+            return f'{obj.discount_value} ₽'
+
+        return f'{obj.discount_percent} %'


Test patch: