55from django .template .response import SimpleTemplateResponse
66from django .contrib .admin .options import IncorrectLookupParameters
77from django .http import HttpResponseRedirect
8-
8+ from django .db import models
9+ from .forms import StatisticsForm
10+ import plotly .express as px
11+ from django .http import HttpResponseBadRequest
912
1013class UserSite (admin .AdminSite ):
1114 enable_nav_sidebar = False
@@ -20,19 +23,30 @@ def has_permission(self, request):
2023class CustomModelAdmin (admin .ModelAdmin ):
2124 show_facets = admin .ShowFacets .NEVER
2225 list_per_page = 10
26+ statistics_form_class = StatisticsForm
27+ has_customisable_statistics = True
2328
2429 def get_urls (self ):
25- info = self .opts .app_label , self .opts .model_name
26- new_urls = [
27- path (
28- 'customisable_statistics/' ,
29- self .admin_site .admin_view (self .customisable_statistics ),
30- name = "%s_%s_customisable_statistics" % info
31- ),
32- ]
30+ new_urls = []
31+ if self .has_customisable_statistics :
32+ info = self .opts .app_label , self .opts .model_name
33+ new_urls = [
34+ path (
35+ 'customisable_statistics/' ,
36+ self .admin_site .admin_view (self .customisable_statistics ),
37+ name = "%s_%s_customisable_statistics" % info
38+ ),
39+ ]
3340 return new_urls + super ().get_urls ()
41+
42+ def changelist_view (self , request , extra_context = None ):
43+ extra_context = extra_context or {}
44+ extra_context ['has_customisable_statistics' ] = self .has_customisable_statistics
45+ return super ().changelist_view (request , extra_context )
3446
3547 def customisable_statistics (self , request ):
48+ if not self .has_customisable_statistics :
49+ return HttpResponseBadRequest ('This model has no customisable statistics' )
3650 try :
3751 cl = self .get_changelist_instance (request )
3852 except IncorrectLookupParameters :
@@ -44,11 +58,37 @@ def customisable_statistics(self, request):
4458 },
4559 )
4660 return HttpResponseRedirect (request .path + "?" + ERROR_FLAG + "=1" )
47- queryset = cl .queryset # уже отфильтрованный
48-
61+ queryset = cl .queryset
62+ chart = None
63+ form = self .statistics_form_class (request .GET or None )
64+ if form .is_valid ():
65+ x_attribute = form .cleaned_data ["x_attribute" ]
66+ y_attribute = form .cleaned_data ["y_attribute" ]
67+ queryset = queryset .values (x_attribute ).annotate (
68+ ** {y_attribute : models .Avg (y_attribute )}
69+ ).order_by (x_attribute )
70+ for item in queryset :
71+ print (type (item [x_attribute ]))
72+ x_list = [item [x_attribute ] for item in queryset ]
73+ y_list = [item [y_attribute ] for item in queryset ]
74+ dict_choices = dict (form .fields ['x_attribute' ].choices )
75+ fig = px .line (
76+ x = x_list , y = y_list ,
77+ labels = {
78+ "x" : dict_choices [x_attribute ],
79+ "y" : dict_choices [y_attribute ]
80+ },
81+ title = f'Среднее значение "{ dict_choices [y_attribute ]} " от "{ dict_choices [x_attribute ]} "'
82+ )
83+ fig .update_layout (title_x = 0.5 )
84+
85+ chart = fig .to_html ()
86+
4987 context = dict (
5088 self .admin_site .each_context (request ),
5189 cl = cl ,
52- title = 'Кастомизируемая статистика'
90+ title = 'Кастомизируемая статистика' ,
91+ form = form ,
92+ chart = chart
5393 )
5494 return render (request , "admin/customisable_statistics.html" , context )
0 commit comments