Способ передать варианты выбора choices в forms.ChoiceField из views.py

Категория: Разработка
Теги: Веб-разработка
Опубликовано: 21 июня 2021 г. 11:00
Просмотров: 226

Способ передать варианты выбора choices в forms.ChoiceField из views.py

Недавно сам столкнулся с проблемой передачи вариантов выбора для поля формы с типом виджета Radio и типом формы forms.ChoiceField из views.py. Зачем, почему и какая проблема, объясню далее. 

Все интернет-статьи и умные советы были о том, что заведи в forms.py или прямо в models.py список, который будет состоять из кортежей:

CHOICES = [
        (1, Вариант 1),
        (2, Вариант 2)
            ]

class TestForm(forms.Form):
    otv1 = forms.ChoiceField(widget=forms.RadioSelect(), choices=CHOICES)

Однако, это всё бесполезно, так как до обработки некоторых строк во views.py я не знаю какие варианты выбора должны быть. В конце концов, один из советчиков предложил создать форму прямо в контроллер-функции, но предупредив о том, что это будет грязный и кривой метод. И да, если так сделать, будут проблемы с POST запросами, но не в этом суть. Недолго подумав, я понял как можно передать варианты выбора choices из функции контроллера в форму, и сделать это можно всего одной строкой, ну ладно, двумя:

choice_field = forms.ChoiceField(label=course.Test1, widget=forms.RadioSelect(),
                                     choices=CHOICES)
form.fields["otv1"] = choice_field

Для того, чтобы вам было проще понять, покажу models.py

class Course(models.Model):
    ...
    Test1 = models.TextField(blank=True, verbose_name='Тест 1')
    Test1_1 = models.TextField(blank=True, verbose_name='Тест 1 - Ответ 1')
    Test1_2 = models.TextField(blank=True, verbose_name='Тест 1 - Ответ 2')
    Test1_3 = models.TextField(blank=True, verbose_name='Тест 1 - Ответ 3')
    Test1_4 = models.TextField(blank=True, verbose_name='Тест 1 - Ответ 4')
    Test1_5 = models.TextField(blank=True, verbose_name='Тест 1 - Правильный ответ')

Также покажу forms.py:

from django import forms
from .models import Course

class TestForm(forms.Form):
    otv1 = forms.CharField(label='Вопрос:')

Ну и фрагмент views.py:

    initial = {}

    CHOICES = [
        (course.Test1_1, course.Test1_1),
        (course.Test1_2, course.Test1_2),
        (course.Test1_3, course.Test1_3),
        (course.Test1_4, course.Test1_4)
            ]
    choice_field = forms.ChoiceField(label=course.Test1, widget=forms.RadioSelect(),
                                     choices=CHOICES)
    form_class = TestForm
    form = form_class(initial=initial)
    form.fields["otv1"] = choice_field

    if request.method == 'POST':
        c_form = form_class(request.POST)
        if c_form.is_valid():
            TestVop = c_form.cleaned_data.get("otv1")
            # print(TestVop)
            if TestVop == course.Test1_5:
                messages.add_message(request, messages.WARNING, 'Правильно!')
            else:
                messages.add_message(request, messages.WARNING, 'Не правильно!')
        else:
            form = c_form
            messages.add_message(request, messages.WARNING, 'Не правильно!')