Skip to content

Commit 52c64ea

Browse files
Refactor NewQuestionForm and optimize views for better performance (#80)
* Refactor NewQuestionForm and optimize views for better performance - Refactored NewQuestionForm to dynamically populate category choices directly from the database, improving efficiency and user experience. - Simplified the handling of minute and second values during form initialization to ensure proper preservation across submissions. - Optimized the home and questions views by reducing unnecessary queries and improving pagination logic. - Enhanced the rendering of questions by caching usernames to minimize database lookups. * Enhance new-question template and form handling - Updated the new-question template to conditionally render alert classes based on message tags, improving user feedback. - Modified the NewQuestionForm to dynamically enable or disable minute and second range fields based on category selection, ensuring a better user experience. - Ensured that minute and second values are preserved across form submissions, enhancing form usability. --------- Co-authored-by: ankitamk14 <ankitamk@gmail.com>
1 parent ffb54ec commit 52c64ea

3 files changed

Lines changed: 131 additions & 202 deletions

File tree

static/website/templates/new-question.html

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
{% if messages %}
66
<ul class="messages">
77
{% for message in messages %}
8-
<li class="{{ message.tags }} alert alert-info">{{ message }}</li>
8+
<li class="{{ message.tags }} alert {% if message.tags == 'error' %}alert-danger{% else %}alert-info{% endif %}">{{ message }}</li>
99
{% endfor %}
1010
</ul>
1111
{% endif %}
@@ -33,10 +33,18 @@ <h4>
3333
{% endif %}
3434
</div>
3535
<div class="col-lg-2 col-md-2 col-sm-2">
36-
{% render_field form.minute_range class+="form-control" disabled="disabled" %}
36+
{% if category %}
37+
{% render_field form.minute_range class+="form-control" %}
38+
{% else %}
39+
{% render_field form.minute_range class+="form-control" disabled="disabled" %}
40+
{% endif %}
3741
</div>
3842
<div class="col-lg-2 col-md-2 col-sm-2">
39-
{% render_field form.second_range class+="form-control" disabled="disabled" %}
43+
{% if category %}
44+
{% render_field form.second_range class+="form-control" %}
45+
{% else %}
46+
{% render_field form.second_range class+="form-control" disabled="disabled" %}
47+
{% endif %}
4048
</div>
4149
</div>
4250
<hr>

website/forms.py

Lines changed: 25 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -9,83 +9,38 @@
99
seconds = ()
1010

1111

12-
def _get_category_choices():
13-
"""Distinct FOSS categories for new-question form, sorted alphabetically."""
14-
categories = list(
15-
TutorialResources.objects.filter(
16-
Q(status=1) | Q(status=2),
17-
language__name='English',
18-
tutorial_detail__foss__show_on_homepage=1,
19-
)
20-
.values_list('tutorial_detail__foss__foss', flat=True)
21-
.distinct()
22-
)
23-
# Remove empty/None and sort case-insensitively (A-Z)
24-
categories = [c for c in categories if c]
25-
categories = sorted(set(categories), key=lambda x: x.lower())
26-
return [('', 'Select a Category')] + [(c, c) for c in categories]
27-
28-
2912
class NewQuestionForm(forms.Form):
30-
category = forms.ChoiceField(
31-
choices=[],
32-
widget=forms.Select(attrs={}),
33-
required=True,
34-
error_messages={'required': 'State field is required.'},
35-
)
13+
category = forms.ChoiceField(choices=[('', 'Select a Category'), ] + list(TutorialResources.objects.filter(
14+
Q(status=1) | Q(status=2), language__name='English',tutorial_detail__foss__show_on_homepage=1).values_list('tutorial_detail__foss__foss',
15+
'tutorial_detail__foss__foss').distinct()),
16+
widget=forms.Select(attrs={}), required=True, error_messages={'required': 'State field is required.'})
3617
title = forms.CharField(max_length=200)
3718
body = forms.CharField(widget=forms.Textarea())
3819

3920
def __init__(self, *args, **kwargs):
40-
# Values that can be passed explicitly (e.g. from the spoken website)
4121
category = kwargs.pop('category', None)
4222
selecttutorial = kwargs.pop('tutorial', None)
23+
4324
select_min = kwargs.pop('minute_range', None)
4425
select_sec = kwargs.pop('second_range', None)
45-
4626
super(NewQuestionForm, self).__init__(*args, **kwargs)
47-
self.fields['category'].choices = _get_category_choices()
4827
tutorial_choices = (
4928
("Select a Tutorial", "Select a Tutorial"),
5029
)
51-
52-
# If no explicit minute/second values were provided (e.g. normal POST),
53-
# preserve any values that came from submitted form data so that
54-
# validation errors (like missing reCAPTCHA) do not wipe them out.
55-
data = args[0] if args else {}
56-
if select_min is None and data and 'minute_range' in data:
57-
select_min = data.get('minute_range')
58-
if select_sec is None and data and 'second_range' in data:
59-
select_sec = data.get('second_range')
60-
61-
# When a minute/second value is available (from the spoken website or a
62-
# previous form submission), show that value as the only selectable
63-
# option; otherwise show the default placeholders.
64-
if select_min:
65-
minutes = (
66-
(select_min, select_min),
67-
)
68-
else:
69-
minutes = (
70-
("", "min"),
71-
)
72-
73-
if select_sec:
74-
seconds = (
75-
(select_sec, select_sec),
76-
)
30+
# Minute/second: when coming from spoken website link we get pre-filled values;
31+
# otherwise show full range so user can select.
32+
if select_min is not None or select_sec is not None:
33+
minutes = ([(select_min, select_min)] if select_min is not None else [("", "min")] + [(str(i), str(i)) for i in range(60)])
34+
seconds = ([(select_sec, select_sec)] if select_sec is not None else [("", "sec")] + [(str(i), str(i)) for i in range(60)])
7735
else:
78-
seconds = (
79-
("", "sec"),
80-
)
36+
minutes = [("", "min")] + [(str(i), str(i)) for i in range(60)]
37+
seconds = [("", "sec")] + [(str(i), str(i)) for i in range(60)]
8138

8239
if not category and args and 'category' in args[0] and args[0]['category']:
8340
category = args[0]['category']
8441
if FossCategory.objects.filter(foss=category).exists():
8542
self.fields['category'].initial = category
86-
tutorials = TutorialDetails.objects.using('spoken').filter(
87-
foss__foss=category
88-
).order_by('level', 'order')
43+
tutorials = TutorialDetails.objects.using('spoken').filter(foss__foss=category)
8944
for tutorial in tutorials:
9045
tutorial_choices += ((tutorial.tutorial, tutorial.tutorial),)
9146
self.fields['tutorial'] = forms.CharField(widget=forms.Select(choices=tutorial_choices))
@@ -94,13 +49,25 @@ def __init__(self, *args, **kwargs):
9449

9550
self.fields['minute_range'] = forms.CharField(widget=forms.Select(choices=minutes))
9651
self.fields['second_range'] = forms.CharField(widget=forms.Select(choices=seconds))
52+
if select_min is not None:
53+
self.fields['minute_range'].initial = select_min
54+
if select_sec is not None:
55+
self.fields['second_range'].initial = select_sec
9756
else:
9857
self.fields['minute_range'] = forms.CharField(widget=forms.Select(choices=minutes))
9958
self.fields['second_range'] = forms.CharField(widget=forms.Select(choices=seconds))
59+
if select_min is not None:
60+
self.fields['minute_range'].initial = select_min
61+
if select_sec is not None:
62+
self.fields['second_range'].initial = select_sec
10063
else:
10164
self.fields['tutorial'] = forms.CharField(widget=forms.Select(choices=tutorial_choices))
10265
self.fields['minute_range'] = forms.CharField(widget=forms.Select(choices=minutes))
10366
self.fields['second_range'] = forms.CharField(widget=forms.Select(choices=seconds))
67+
if select_min is not None:
68+
self.fields['minute_range'].initial = select_min
69+
if select_sec is not None:
70+
self.fields['second_range'].initial = select_sec
10471

10572

10673
class AnswerQuesitionForm(forms.Form):

0 commit comments

Comments
 (0)