Django表单验证在重写__init__动态创建表单时失败



我正在Django中编写一个预测应用程序。在基本级别上,它从API中提取匹配,填充数据库,并最终允许用户对尚未进行的匹配进行预测。由于在此之前我不知道一场比赛会有多少场比赛,所以我想创建一个表格,根据需要动态添加尽可能多的字段。

我目前有一个";工作";版本,但这会在以后产生问题。这是工作版本:(公平的警告,这是我的测试,所以请原谅命名约定(

视图.py

def ftest(request, contest_id):
matches_list = Matches.objects.filter(
matches_contest_pk__id = contest_id
).filter(
matches_complete = False
).order_by(
'-matches_start_time'
)
matches = [
f'{match.matches_team_1} vs. {match.matches_team_2}'
for match in matches_list
]
if request.method == 'POST':
form = TestForm(form_fields = matches, data=request.POST)
if form.is_valid():
return HttpResponseRedirect('/thanks/')
else:
print(form.errors)
else:
form = TestForm(form_fields = matches)
context = {
'form': form,
}
return render(request, 'predictions/test.html', context)

表单.py

from django import forms
from .models import Matches
class TestForm(forms.Form):
def __init__(self, *args, **kwargs):
form_fields = kwargs.pop('form_fields', None)
super(TestForm, self).__init__(*args, **kwargs)
for field in form_fields:
self.fields[field] = forms.CharField(label = f'{field}', max_length = 100)

正如我所说,这是可行的,但理想情况下,我希望将每个字段的id设置为数据库中的实际id。对此,我的解决方案是更改视图以通过form_fields发送dict列表,并更新表单以使用该列表。这就是它的样子:

视图.py

def ftest(request, contest_id):
matches_list = Matches.objects.filter(
matches_contest_pk__id = contest_id
).filter(
matches_complete = False
).order_by(
'-matches_start_time'
)
matches = [
{ 'label': f'{match.matches_team_1} vs. {match.matches_team_2}', 'id': match.id, }
for match in matches_list
]
if request.method == 'POST':
form = TestForm(form_fields = matches, data=request.POST)
if form.is_valid():
return HttpResponseRedirect('/thanks/')
else:
print(form.errors)
else:
form = TestForm(form_fields = matches)
context = {
'form': form,
}
return render(request, 'predictions/test.html', context)

表单.py

from django import forms
from .models import Matches
class TestForm(forms.Form):
def __init__(self, *args, **kwargs):
form_fields = kwargs.pop('form_fields', None)
super(TestForm, self).__init__(*args, **kwargs)
for field in form_fields:
self.fields[field['id']] = forms.CharField(label = field['label'], max_length = 100)

但是,通过此更改,表单无法通过验证。它只是为每个字段抛出一个This field is required.错误。理想情况下,我希望用户返回到同一页面,并在字段中填写他们的预测。关于如何解决这个问题有什么建议吗?我是从错误的角度来处理这个问题,还是误解了表单在Django中的工作方式?

已解决。

问题出在我发送给表单创建方法的内容上。当我创建dict时,它是这样做的:

matches = [
{ 'label': f'{match.matches_team_1} vs. {match.matches_team_2}', 'id': match.id, }
for match in matches_list
]

原来问题出在"id"键上。我给它分配了一个整数,它需要是表单创建中的字符串。因此,解决方案看起来像:

matches = [
{ 'label': f'{match.matches_team_1} vs. {match.matches_team_2}', 'id': str(match.id), }
for match in matches_list
]

最新更新