1- from typing import Any
1+ from typing import Any , Literal , Sequence
2+ from typing_extensions import override
23from django .contrib import admin
34from django import forms
45from django .contrib .admin .views .autocomplete import AutocompleteJsonView
@@ -41,28 +42,44 @@ class BaseAdmin(admin.ModelAdmin):
4142 Base admin class to add common attributes.
4243 Such as created_at and updated_at fields.
4344 """
45+ def _get_fields_to_display (self ) -> list [str ]:
46+ return self ._get_fields_to_display_as_readonly ()
4447
45- def get_readonly_fields (self , request : HttpRequest , obj : Any | None = ... ) -> list [str ] | tuple [ Any , ... ]:
46- return list ( super (). get_readonly_fields ( request , obj )) + [
47- ' created_at' ,
48- ' updated_at' ,
48+ def _get_fields_to_display_as_readonly (self ) -> list [str ]:
49+ return [
50+ " created_at" ,
51+ " updated_at" ,
4952 ]
5053
54+ def get_readonly_fields (
55+ self , request : HttpRequest , obj : Any | None = ...
56+ ) -> list [str ] | tuple [Any , ...]:
57+ return (
58+ list (super ().get_readonly_fields (request , obj ))
59+ + list (self ._get_fields_to_display_as_readonly ())
60+ )
61+
62+ def get_list_display (self , request ) -> list [str ]:
63+ return self ._get_fields_to_display () + list (super ().get_list_display (request ))
64+
5165
5266class SaleAdmin (BaseAdmin ):
53- list_filter = ('room' , 'timestamp' )
54- list_display = (
55- 'get_username' ,
56- 'get_fullname' ,
57- 'get_product_name' ,
58- 'get_room_name' ,
59- 'timestamp' ,
60- 'get_price_display' ,
61- )
67+ list_filter = ("room" , "timestamp" )
68+
69+ def _get_fields_to_display (self ):
70+ return [
71+ "get_username" ,
72+ "get_fullname" ,
73+ "get_product_name" ,
74+ "get_room_name" ,
75+ "timestamp" ,
76+ "get_price_display" ,
77+ ] + super ()._get_fields_to_display ()
78+
6279 actions = [refund ]
63- search_fields = [' ^member__username' , ' =product__id' , ' product__name' ]
64- valid_lookups = ' member'
65- autocomplete_fields = [' member' , ' product' ]
80+ search_fields = [" ^member__username" , " =product__id" , " product__name" ]
81+ valid_lookups = " member"
82+ autocomplete_fields = [" member" , " product" ]
6683
6784 class Media :
6885 css = {'all' : ('stregsystem/select2-stregsystem.css' ,)}
@@ -125,33 +142,36 @@ def toggle_active_selected_products(modeladmin, request, queryset):
125142
126143
127144class ProductActivatedListFilter (admin .SimpleListFilter ):
128- title = ' activated'
129- parameter_name = ' activated'
145+ title = " activated"
146+ parameter_name = " activated"
130147
131148 def lookups (self , request , model_admin ):
132149 return (
133- (' Yes' , ' Yes' ),
134- ('No' , 'No' ),
150+ (" Yes" , " Yes" ),
151+ ("No" , "No" ),
135152 )
136153
137154 def queryset (self , request , queryset ):
138- if self .value () == ' Yes' :
155+ if self .value () == " Yes" :
139156 return make_active_productlist_query (queryset )
140- elif self .value () == 'No' :
157+ elif self .value () == "No" :
141158 return make_inactive_productlist_query (queryset )
142159 else :
143160 return queryset
144161
145162
146163class ProductAdmin (BaseAdmin ):
147- search_fields = ('name' , 'price' , 'id' )
148- list_filter = (ProductActivatedListFilter , 'deactivate_date' , 'price' )
149- list_display = (
150- 'activated' ,
151- 'id' ,
152- 'name' ,
153- 'get_price_display' ,
154- )
164+ search_fields = ("name" , "price" , "id" )
165+ list_filter = (ProductActivatedListFilter , "deactivate_date" , "price" )
166+
167+ def _get_fields_to_display (self ):
168+ return [
169+ "activated" ,
170+ "id" ,
171+ "name" ,
172+ "get_price_display" ,
173+ ] + super ()._get_fields_to_display ()
174+
155175 fields = (
156176 "name" ,
157177 "price" ,
@@ -163,8 +183,8 @@ class ProductAdmin(BaseAdmin):
163183 "caffeine_content_mg" ,
164184 )
165185
166- def get_readonly_fields (self , request : HttpRequest , obj : Any | None = ... ) -> list [str ] | tuple [ Any , ... ]:
167- return list ( super ().get_readonly_fields ( request , obj )) + [ 'get_bought' ]
186+ def _get_fields_to_display_as_readonly (self ) -> list [str ]:
187+ return [ "get_bought" ] + super ()._get_fields_to_display_as_readonly ()
168188
169189 actions = [toggle_active_selected_products ]
170190 filter_horizontal = ('categories' , 'rooms' )
@@ -191,13 +211,16 @@ def activated(self, product):
191211
192212class NamedProductAdmin (BaseAdmin ):
193213 search_fields = (
194- 'name' ,
195- 'product' ,
196- )
197- list_display = (
198- 'name' ,
199- 'product' ,
214+ "name" ,
215+ "product" ,
200216 )
217+
218+ def _get_fields_to_display (self ):
219+ return [
220+ "name" ,
221+ "product" ,
222+ ] + super ()._get_fields_to_display ()
223+
201224 fields = (
202225 'name' ,
203226 'product' ,
@@ -208,7 +231,11 @@ class NamedProductAdmin(BaseAdmin):
208231
209232
210233class CategoryAdmin (BaseAdmin ):
211- list_display = ('name' , 'items_in_category' )
234+ def _get_fields_to_display (self ):
235+ return [
236+ "name" ,
237+ "items_in_category" ,
238+ ] + super ()._get_fields_to_display ()
212239
213240 def items_in_category (self , obj ):
214241 return obj .product_set .count ()
@@ -229,9 +256,18 @@ def clean_username(self):
229256
230257class MemberAdmin (BaseAdmin ):
231258 form = MemberForm
232- list_filter = ('want_spam' ,)
233- search_fields = ('username' , 'firstname' , 'lastname' , 'email' )
234- list_display = ('username' , 'firstname' , 'lastname' , 'balance' , 'email' , 'notes' )
259+ list_filter = ("want_spam" ,)
260+ search_fields = ("username" , "firstname" , "lastname" , "email" )
261+
262+ def _get_fields_to_display (self ):
263+ return [
264+ "username" ,
265+ "firstname" ,
266+ "lastname" ,
267+ "balance" ,
268+ "email" ,
269+ "notes" ,
270+ ] + super ()._get_fields_to_display ()
235271
236272 # fieldsets is like fields, except that they are grouped and with descriptions
237273 fieldsets = (
@@ -276,10 +312,17 @@ def get_queryset(self):
276312
277313
278314class PaymentAdmin (BaseAdmin ):
279- list_display = ('get_username' , 'timestamp' , 'get_amount_display' , 'is_mobilepayment' )
280- valid_lookups = 'member'
281- search_fields = ['member__username' ]
282- autocomplete_fields = ['member' ]
315+ def _get_fields_to_display (self ):
316+ return [
317+ "get_username" ,
318+ "timestamp" ,
319+ "get_amount_display" ,
320+ "is_mobilepayment" ,
321+ ] + super ()._get_fields_to_display ()
322+
323+ valid_lookups = "member"
324+ search_fields = ["member__username" ]
325+ autocomplete_fields = ["member" ]
283326
284327 class Media :
285328 css = {'all' : ('stregsystem/select2-stregsystem.css' ,)}
@@ -305,18 +348,20 @@ def is_mobilepayment(self, obj):
305348
306349
307350class MobilePaymentAdmin (BaseAdmin ):
308- list_display = (
309- 'payment' ,
310- 'customer_name' ,
311- 'comment' ,
312- 'timestamp' ,
313- 'transaction_id' ,
314- 'get_amount_display' ,
315- 'status' ,
316- )
317- valid_lookups = 'member'
318- search_fields = ['member__username' ]
319- autocomplete_fields = ['member' , 'payment' ]
351+ def _get_fields_to_display (self ):
352+ return [
353+ "payment" ,
354+ "customer_name" ,
355+ "comment" ,
356+ "timestamp" ,
357+ "transaction_id" ,
358+ "get_amount_display" ,
359+ "status" ,
360+ ] + super ()._get_fields_to_display ()
361+
362+ valid_lookups = "member"
363+ search_fields = ["member__username" ]
364+ autocomplete_fields = ["member" , "payment" ]
320365
321366 class Media :
322367 css = {'all' : ('stregsystem/select2-stregsystem.css' ,)}
@@ -343,10 +388,20 @@ def really_delete_selected(self, _, queryset):
343388
344389
345390class LogEntryAdmin (BaseAdmin ):
346- date_hierarchy = 'action_time'
347- list_filter = ['content_type' , 'action_flag' ]
348- search_fields = ['object_repr' , 'change_message' , 'user__username' ]
349- list_display = ['action_time' , 'user' , 'content_type' , 'object_id' , 'action_flag' , 'change_message' , 'object_repr' ]
391+ date_hierarchy = "action_time"
392+ list_filter = ["content_type" , "action_flag" ]
393+ search_fields = ["object_repr" , "change_message" , "user__username" ]
394+
395+ def _get_fields_to_display (self ):
396+ return [
397+ "action_time" ,
398+ "user" ,
399+ "content_type" ,
400+ "object_id" ,
401+ "action_flag" ,
402+ "change_message" ,
403+ "object_repr" ,
404+ ] + super ()._get_fields_to_display ()
350405
351406 def has_view_permission (self , request , obj = None ):
352407 return request .user .is_superuser
@@ -362,7 +417,16 @@ def has_delete_permission(self, request, obj=None):
362417
363418
364419class ThemeAdmin (BaseAdmin ):
365- list_display = ["name" , "override" , "begin_month" , "begin_day" , "end_month" , "end_day" ]
420+ def _get_fields_to_display (self ):
421+ return [
422+ "name" ,
423+ "override" ,
424+ "begin_month" ,
425+ "begin_day" ,
426+ "end_month" ,
427+ "end_day" ,
428+ ] + super ()._get_fields_to_display ()
429+
366430 search_fields = ["name" ]
367431
368432 @admin .action (description = "Do not force chosen themes" )
@@ -381,11 +445,13 @@ def force_hide(modeladmin, request, queryset):
381445
382446
383447class ProductNoteAdmin (BaseAdmin ):
384- search_fields = ('active' , 'text' )
385- list_display = (
386- 'active' ,
387- 'text' ,
388- )
448+ search_fields = ("active" , "text" )
449+
450+ def _get_fields_to_display (self ):
451+ return [
452+ "active" ,
453+ "text" ,
454+ ] + super ()._get_fields_to_display ()
389455
390456 actions = [toggle_active_selected_products ]
391457
0 commit comments