我正在尝试创建一个在运行时生成带有字段的表单的进程。此表单是一个简单的表单,而不是模型表单。它包含许多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字段的标签。
我认为原因是request.POST
中的QueryDict数据与从数据库表中获取的原始词典列表的形式不同。以下是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数据重新创建表单并检查表单在提交时是否有效?
答案 0 :(得分:0)
我明白了。我没有将POST值传递给表单,而是将其作为表单的**kwargs
参数传递,这是完全错误的。因此,无法验证表单。单个代码更改解决了我的问题。
ratingform = ExampleForm(request.POST, rating=interview_rating)