@@ -103,59 +103,67 @@ def analytics(request):
103103 datatype_interest_counts = {}
104104 datatype_provider_query_counts = {}
105105
106- for article in Article .objects .all ():
107- if article .datatype not in datatype_interest_counts :
108- datatype_interest_counts [article .datatype ] = {
109- 'views' : 0 ,
110- 'queries' : 0
111- }
112-
113- for query in QueryLog .objects .all ():
114- # Query logs have datatypes stored
115- # with underscores instead of spaces
106+ for datatype in Article .datatypes ().values_list ('datatype' , flat = True ):
107+ datatype_interest_counts [datatype ] = {
108+ 'views' : 0 ,
109+ 'queries' : 0
110+ }
111+
112+ # Process query logs
113+ for query in QueryLog .objects .iterator ():
116114 datatype_name = " " .join (query .datatype .split ("_" ))
117115 if datatype_name in datatype_interest_counts :
118- datatype_interest_counts [datatype_name ]['queries' ] += 1
119-
120- if datatype_name not in datatype_provider_query_counts :
121- datatype_provider_query_counts [datatype_name ] = {
122- 'sources' : {},
123- 'destinations' : {},
124- 'transitions' : {}
125- }
126- if query .source in datatype_provider_query_counts [datatype_name ]['sources' ]:
127- datatype_provider_query_counts [datatype_name ]['sources' ][query .source ] += 1 ;
128- else :
129- datatype_provider_query_counts [datatype_name ]['sources' ][query .source ] = 1 ;
130-
131- destination = query .destination if query .destination else 'None selected'
132- if destination in datatype_provider_query_counts [datatype_name ]['destinations' ]:
133- datatype_provider_query_counts [datatype_name ]['destinations' ][destination ] += 1 ;
134- else :
135- datatype_provider_query_counts [datatype_name ]['destinations' ][destination ] = 1 ;
136-
137- transition = query .source + ' -> ' + destination
138-
139- if transition in datatype_provider_query_counts [datatype_name ]['transitions' ]:
140- datatype_provider_query_counts [datatype_name ]['transitions' ][transition ] += 1
141- else :
142- datatype_provider_query_counts [datatype_name ]['transitions' ][transition ] = 1
143-
144- for view in TrackArticleView .objects .select_related ("article" ).all ():
145- datatype_interest_counts [view .article .datatype ]['views' ] += 1
146-
147-
148- sentiment_query = Article .objects .annotate (happy_count = Count ("feedback" , filter = Q (feedback__reaction = 'happy' )),
149- sad_count = Count ("feedback" , filter = Q (feedback__reaction = 'sad' )))
150- article_sentiment = [{'name' : article .name ,
151- 'title' : textwrap .shorten (article .title , width = 50 ),
152- 'happy_count' : range (article .happy_count ),
153- 'sad_count' : range (article .sad_count )} for article in sentiment_query .order_by ('-sad_count' )]
154-
116+ datatype_interest_counts [datatype_name ]['queries' ] += 1
117+
118+ if datatype_name not in datatype_provider_query_counts :
119+ datatype_provider_query_counts [datatype_name ] = {
120+ 'sources' : {},
121+ 'destinations' : {},
122+ 'transitions' : {}
123+ }
124+
125+ sources = datatype_provider_query_counts [datatype_name ]['sources' ]
126+ sources [query .source ] = sources .get (query .source , 0 ) + 1
127+
128+ # Update destination counts
129+ destination = query .destination if query .destination else 'None selected'
130+ destinations = datatype_provider_query_counts [datatype_name ]['destinations' ]
131+ destinations [destination ] = destinations .get (destination , 0 ) + 1
132+
133+ # Update transition counts
134+ transition = f"{ query .source } -> { destination } "
135+ transitions = datatype_provider_query_counts [datatype_name ]['transitions' ]
136+ transitions [transition ] = transitions .get (transition , 0 ) + 1
137+
138+ # Count views using database aggregation
139+ view_counts = (TrackArticleView .objects
140+ .values ('article__datatype' )
141+ .annotate (total = Count ('id' )))
142+
143+ for vc in view_counts :
144+ datatype = vc ['article__datatype' ]
145+ if datatype in datatype_interest_counts :
146+ datatype_interest_counts [datatype ]['views' ] = vc ['total' ]
147+
148+ sentiment_query = (Article .objects
149+ .values ('name' , 'title' )
150+ .annotate (
151+ happy_count = Count ('feedback' , filter = Q (feedback__reaction = 'happy' )),
152+ sad_count = Count ('feedback' , filter = Q (feedback__reaction = 'sad' ))
153+ )
154+ .order_by ('-sad_count' ))
155+
156+ article_sentiment = [{
157+ 'name' : article ['name' ],
158+ 'title' : textwrap .shorten (article ['title' ], width = 50 ),
159+ 'happy_count' : range (article ['happy_count' ]),
160+ 'sad_count' : range (article ['sad_count' ])
161+ } for article in sentiment_query ]
155162
156163 stats = json .dumps ({
157164 'datatypeInterest' : datatype_interest_counts ,
158165 'providerQueriesByDatatype' : datatype_provider_query_counts
159166 })
160167
161- return TemplateResponse (request , "admin/analytics.html" , {'stats' : stats , 'article_sentiment' : article_sentiment })
168+ return TemplateResponse (request , "admin/analytics.html" ,
169+ {'stats' : stats , 'article_sentiment' : article_sentiment })
0 commit comments