Проверьте информацию о полях формы, сгенерированных во время выполнения в Django - PullRequest
0 голосов
/ 25 мая 2018

Я пытаюсь создать процесс, который генерирует форму со своими полями во время выполнения.Эта форма является простой формой, а не моделью.Он содержит несколько полей RadioSelect, TextArea и IntegerField.Количество полей переключателей, которые будут сгенерированы, определяется данными, полученными из таблицы базы данных.Данные находятся в формате JSON, который содержит список словарей при разборе и выглядит следующим образом:

[
  {'criteria': 'design', 'description': 'aaa, bbb'}, 
  {'criteria': 'design', 'description': 'ccc, ddd'}, 
  {'criteria': 'design', 'description': 'eee, fff'}, 
  {'criteria': 'design', 'description': 'ggg, hhh'}, 
  {'criteria': 'design', 'description': 'iii, jjj'}, 
  {'criteria': 'design', 'description': 'kkk, lll'},
]

В приведенном выше примере имеется 6 словарей, что означает, что будет сгенерировано 6 полей RadioSelect.Если данные JSON содержат 10 словарей, то будут сгенерированы 10 полей RadioSelect.Поля TextArea и IntegerField всегда присутствуют в форме.

Когда форма отправлена, я хотел бы проверить форму и, если нет ошибок, получить данные из формы, выполнить некоторые операции с данными,сохранить данные в другой таблице базы данных и отобразить форму с сохраненными данными.Если есть ошибки, то отобразите форму с ошибками, которые произошли.

Я хотел бы закодировать этот процесс, используя только одно представление и один шаблон.Вот упрощенная выдержка из моего кода

forms.py

class ExampleForm(forms.Form):
    def __init__(self, *args, **kwargs):
        radio_choices = (
            ('0', '0'),
            ('1', '1'),
            ('2', '2'),
            ('3', '3'),
            ('4', '4'),
        )

        ratings = kwargs.pop('rating')
        super(ExampleForm, self).__init__(*args, **kwargs)
        if isinstance(ratings, QueryDict):
            self.ratings = ratings.dict()
            # stuck here
        else:
            self.ratings = ratings
            # loop through the dict and create radio button for each of them
            for idx, rating in enumerate(self.ratings, start=1):
                field = forms.TypedChoiceField(
                    label=rating["criteria"],
                    choices=radio_choices,
                    coerce=lambda x: bool(int(x)),
                    widget=forms.RadioSelect,
                    initial=0,
                    required=False,
                )
                self.fields["criteria{}".format(idx)] = field

        self.fields["details"] = forms.CharField(
            label="Details",
            # max_length=80,
            required=False,
            widget=forms.Textarea(attrs={
                'placeholder': 'Type any other impressions you have',
            }),
            help_text='Write any message here',
        )

        self.fields["overall_evaluation"] = forms.IntegerField(
            label="Overall Evaluation",
            max_value=4,
            min_value=0,
            required=True,
        )

views.py

from .models import Rating, Result
def formtest(request):
    if request.method == "POST":
        # request.POST contains a QueryDict which is immutable
        # To get a mutable object call the copy() method on request.POST??
        ratingform = ExampleForm(rating=request.POST or None) # fails here

        # call is_valid here??
        # Process data
        # Save data in Result
    else:
        rating = Rating.objects.get(pk=4).criteria
        ratingform = ExampleForm(rating=json.loads(rating))

return render(request, 'formtest.html', context={
    'form': ratingform,
})

При первом доступе к форме я могу создатьформа без каких-либо проблем, но после отправки формы, я не только получаю ошибку, я думаю, что я не смогу сгенерировать метки для полей RadioSelect.

Я думаю, что причина в том, что данные QueryDict в request.POST имеют форму, отличную от первоначального списка словарей, полученных из таблицы базы данных.Вот как выглядит request.POST

<QueryDict: {'csrfmiddlewaretoken': ['sfdgbif'], 'criteria1': [
'0'], 'criteria2': ['0'], 'criteria3': ['0'], 'criteria4': ['0'], 'criteria5': ['0'], 'criteria6': ['0'], 'details': ['very good product'], 'overall_evaluation': ['3']}>

Ключи criteria1..criteria6 отличаются от ключа criteria в исходном списке словарей и содержат только цифры, которые являются значениями, выбранными изпереключатели перед отправкой формы.Одним из способов может быть изменение QueryDict, но я не знаю, является ли это хорошим способом для этого.

Как я могу воссоздать форму с данными request.POST и проверить, является ли форма действительнойотправить?

1 Ответ

0 голосов
/ 25 мая 2018

Я понял это.Я не передал значения POST в форму, вместо этого я передал его как аргумент **kwargs формы, что совершенно неверно.В результате форма не может быть проверена.Одно изменение кода решило мою проблему.

ratingform = ExampleForm(request.POST, rating=interview_rating)
...