Я пытаюсь создать процесс, который генерирует форму со своими полями во время выполнения.Эта форма является простой формой, а не моделью.Он содержит несколько полей 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 и проверить, является ли форма действительнойотправить?