Skip to content

Commit d09ef28

Browse files
authored
Refactor question data handling in templates and views (#67)
- Updated template to use cached user and last post user fields for improved performance. - Changed answer count retrieval to use a new annotation in the view. - Enhanced the last_post_user method to handle cases where the user may not exist. - Optimized user fetching to reduce database queries by bulk fetching user data for displayed questions.
1 parent dac8229 commit d09ef28

3 files changed

Lines changed: 47 additions & 27 deletions

File tree

static/website/templates/index.html

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -169,12 +169,12 @@ <h3 align="center">Answers</h3>
169169
</td>
170170

171171
<td>
172-
{{ question.answer_set.count }}
172+
{{ question.answer_count }}
173173
</td>
174174

175175
<td>
176-
<span class="title" data-toggle="tooltip" data-placement="top" title="{{ question.user }}">
177-
{{ question.user|truncatechars:10 }}
176+
<span class="title" data-toggle="tooltip" data-placement="top" title="{{ question.cached_user }}">
177+
{{ question.cached_user|truncatechars:10 }}
178178
</span>
179179
</td>
180180
</tr>
@@ -250,8 +250,8 @@ <h3 align="center">Answers</h3>
250250
</span>
251251
</td>
252252
<td>
253-
<span class="title" data-toggle="tooltip" data-placement="top" title="{{ question.user }}">
254-
{{ question.user|truncatechars:10 }}
253+
<span class="title" data-toggle="tooltip" data-placement="top" title="{{ question.cached_user }}">
254+
{{ question.cached_user|truncatechars:10 }}
255255
</span>
256256
</td>
257257

@@ -263,8 +263,8 @@ <h3 align="center">Answers</h3>
263263
</span>
264264
</td>
265265
<td>
266-
<span class="title" data-toggle="tooltip" data-placement="top" title="{{ question.last_post_user }}">
267-
{{ question.last_post_user|truncatechars:10 }}
266+
<span class="title" data-toggle="tooltip" data-placement="top" title="{{ question.cached_last_post_user }}">
267+
{{ question.cached_last_post_user|truncatechars:10 }}
268268
</span>
269269
</td>
270270

@@ -273,7 +273,7 @@ <h3 align="center">Answers</h3>
273273
</td>
274274

275275
<td>
276-
{{ question.answer_set.count }}
276+
{{ question.answer_count }}
277277
</td>
278278
</tr>
279279
{% endfor %}
@@ -350,8 +350,8 @@ <h3 align="center">Answers</h3>
350350
</span>
351351
</td>
352352
<td>
353-
<span class="title" data-toggle="tooltip" data-placement="top" title="{{ question.user }}">
354-
{{ question.user|truncatechars:10 }}
353+
<span class="title" data-toggle="tooltip" data-placement="top" title="{{ question.cached_user }}">
354+
{{ question.cached_user|truncatechars:10 }}
355355
</span>
356356
</td>
357357

@@ -363,8 +363,8 @@ <h3 align="center">Answers</h3>
363363
</span>
364364
</td>
365365
<td>
366-
<span class="title" data-toggle="tooltip" data-placement="top" title="{{ question.last_post_user }}">
367-
{{ question.last_post_user|truncatechars:10 }}
366+
<span class="title" data-toggle="tooltip" data-placement="top" title="{{ question.cached_last_post_user }}">
367+
{{ question.cached_last_post_user|truncatechars:10 }}
368368
</span>
369369
</td>
370370

@@ -373,7 +373,7 @@ <h3 align="center">Answers</h3>
373373
</td>
374374

375375
<td>
376-
{{ question.answer_set.count }}
376+
{{ question.answer_count }}
377377
</td>
378378
</tr>
379379
{% endfor %}

website/models.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@ def user(self):
2525
return user.username
2626

2727
def last_post_user(self):
28-
user = User.objects.get(id=self.last_post_by)
29-
return user.username
28+
user = User.objects.filter(id=self.last_post_by).first()
29+
return user.username if user else "Unknown User"
3030

3131
class Meta:
3232
get_latest_by = "date_created"

website/views.py

Lines changed: 32 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -32,14 +32,35 @@
3232

3333

3434
def home(request):
35-
questions = Question.objects.filter(status=1).order_by('date_created').reverse()[:100]
36-
active_questions = Question.objects.filter(status=1, last_active__isnull=False).order_by('last_active').reverse()[:100]
37-
35+
# Base query with answer count annotation
36+
base_queryset = Question.objects.annotate(answer_count=Count('answer'))
37+
38+
questions = base_queryset.filter(status=1).order_by('-date_created')[:100]
39+
active_questions = base_queryset.filter(status=1, last_active__isnull=False).order_by('-last_active')[:100]
40+
3841
# Retrieve latest questions per category for the slider
3942
subquery = Question.objects.filter(category=OuterRef('category'), status=1).values('category').annotate(max_date=Max('date_created')).values('max_date')
40-
slider_questions = Question.objects.filter(
43+
slider_questions = base_queryset.filter(
4144
date_created=Subquery(subquery), status=1
4245
).order_by('category')
46+
47+
# spam questions
48+
spam_questions = base_queryset.filter(status=2).order_by('-last_active')[:100]
49+
50+
# Bulk fetch users for all displayed questions to avoid N+1
51+
all_questions = list(questions) + list(active_questions) + list(slider_questions) + list(spam_questions)
52+
uids = set()
53+
for q in all_questions:
54+
uids.add(q.uid)
55+
if q.last_post_by:
56+
uids.add(q.last_post_by)
57+
58+
users = {u.id: u.username for u in User.objects.filter(id__in=uids)}
59+
60+
# Attach usernames to question objects so templates don't trigger queries
61+
for q in all_questions:
62+
q.cached_user = users.get(q.uid, "Unknown User")
63+
q.cached_last_post_user = users.get(q.last_post_by, "Unknown User") if q.last_post_by else "Unknown User"
4364

4465
# Mapping of foss name as in spk db & its corresponding category name in forums db
4566
category_fosses = {val.replace(" ", "-") : val for val in categories}
@@ -60,18 +81,17 @@ def home(request):
6081
if foss not in category_question_map:
6182
category_question_map[foss] = None
6283

63-
# spam questions
64-
spam_questions = Question.objects.filter(status=2).order_by('last_active').reverse()[:100]
6584
# Sort category_question_map by category name
6685
category_question_map = dict(sorted(category_question_map.items(), key= lambda item: item[0].lower()))
6786
show_spam_list = is_administrator(request.user) or is_forumsadmin(request.user)
87+
6888
context = {
69-
'questions': questions,
70-
'active_questions':active_questions,
71-
'spam_questions': spam_questions,
72-
'category_question_map': category_question_map,
73-
'show_spam_list': show_spam_list
74-
}
89+
'questions': questions,
90+
'active_questions': active_questions,
91+
'spam_questions': spam_questions,
92+
'category_question_map': category_question_map,
93+
'show_spam_list': show_spam_list
94+
}
7595
return render(request, "website/templates/index.html", context)
7696

7797

0 commit comments

Comments
 (0)