如何在 Django 中验证表单集
How to validate a formset in dajngo
我正在使用 formset 将我的数据输入到数据库中,但出于某种原因,每当我在终端中测试并调用 .is_valid() 时,它就无法验证,它只是 returns false 无论我尝试什么。这是我的 views.py 和 forms.py 中的代码。任何帮助将不胜感激!
# Advanced Subjects (Advanced Biology)
def form_5_entry_biology_view(self, request):
current_teacher = User.objects.get(email=request.user.email)
logged_school = current_teacher.school_number
students_involved = User.objects.get(school_number=logged_school).teacher.all()
data = {"student_name": students_involved}
formset_data = AdvancedStudents.objects.filter(class_studying="Form V", combination="PCB")
student_formset = formset_factory(AdvancedBiologyForm, extra=0)
initial = []
for element in formset_data:
initial.append({"student_name": element})
formset = student_formset(request.POST or None, initial=initial)
print(formset.is_valid())
context = {
"students": students_involved,
"formset": formset,
"class_of_students": "Form V",
"subject_name": "Advanced Biology",
}
return render(request, "analyzer/marks_entry/marks_entry_page.html", context)
这是我的 forms.py
class AdvancedBiologyForm(forms.ModelForm):
student_name = forms.CharField()
class Meta:
model = ResultsALevel
fields = ('student_name', 'advanced_biology_1', 'advanced_biology_2',
'advanced_biology_3',)
在使用 request.POST
和 is_valid()
之前,您可能需要检查是否确实存在 post 请求或是否刚刚查看了该页面:
def form_5_entry_biology_view(self, request):
current_teacher = User.objects.get(email=request.user.email)
logged_school = current_teacher.school_number
students_involved = User.objects.get(school_number=logged_school).teacher.all()
data = {"student_name": students_involved}
formset_data = AdvancedStudents.objects.filter(class_studying="Form V", combination="PCB")
# Here you are creating the formset using the model
student_formset = formset_factory(AdvancedBiologyForm, extra=0)
# Here you are generating your initial data
initial = []
for element in formset_data:
initial.append({"student_name": element})
# Here you are using the initial data to create pre-populated
# forms with it using the formset.
# These forms will be displayed when the page loads.
formset = student_formset(initial=initial)
context = {
"students": students_involved,
"formset": formset,
"class_of_students": "Form V",
"subject_name": "Advanced Biology",
}
# But if the user hits the "submit"-Button...
if request.method == 'POST':
# ... you don't want to have the formset with your
# initial data. Instead you want the entries by the user
# which are transmitted in request.POST to populate the
# formset forms.
formset = student_formset(request.POST or None)
# Now you can validate the formset with the fields which
# got input the the user; not the "initial" data like in
# your original code
if formset.is_valid():
# This runs formset validation.
# You can define your own formset validations like
# you would for models/forms.
for form in formset:
# And / Alternatively:
# you could in theory also add another "if form.is_valid():" in here
# This would trigger any validation on the
# model/form; not the validators on the formset.
form.save()
return HttpResponseRedirect(...
return render(request, "analyzer/marks_entry/marks_entry_page.html", context)
否则您可能会在未绑定的表单上调用 is_valid()
。
来自 Django docs:
If the form is submitted using a POST request, the view will once again create a form instance and populate it with data from the request: form = NameForm(request.POST) This is called “binding data to the form” (it is now a bound form).
基本上,如果一个表单是空的,它就是未绑定的,如果它填充了数据,它就会在 POST 之后绑定。当你打开一个页面并立即尝试“is_valid()”时,它基本上总是错误的,因为你正在检查一个空表单是否有效;它可能永远不会。
指出错误:
formset = student_formset(request.POST or None, initial=initial)
print(formset.is_valid())
这是无效的。因为初始值不等于用“真实”值填充表单字段。因此,它会尝试用 request.POST or None
填充表单中的字段。
但是您没有 if request.method == 'POST':
条件。因此,您的代码将 运行 通过,然后到达最后一行代码,即显示页面的 return 语句。
这意味着您的代码甚至在用户看到页面之前就验证了 request.POST or None
。因此,用户不可能已经输入数据并点击提交。这意味着没有 POST-请求,所以它总是变成 None
。因此,您基本上是在一个没有字段值的表单上调用 is_valid()
,这会导致验证失败。
编辑 1:我刚注意到你的 forms.py
你写了:
fields = ('student_name', 'advanced_biology_1', 'advanced_biology_2',
'advanced_biology_3',)
这个should be a list改为:
fields = ['student_name', 'advanced_biology_1', 'advanced_biology_2',
'advanced_biology_3',]
编辑 2:修复了错误的变量名
编辑 3:添加了广泛的评论以阐明代码中发生的事情
编辑 4:更清楚地指出问题的原因。
我正在使用 formset 将我的数据输入到数据库中,但出于某种原因,每当我在终端中测试并调用 .is_valid() 时,它就无法验证,它只是 returns false 无论我尝试什么。这是我的 views.py 和 forms.py 中的代码。任何帮助将不胜感激!
# Advanced Subjects (Advanced Biology)
def form_5_entry_biology_view(self, request):
current_teacher = User.objects.get(email=request.user.email)
logged_school = current_teacher.school_number
students_involved = User.objects.get(school_number=logged_school).teacher.all()
data = {"student_name": students_involved}
formset_data = AdvancedStudents.objects.filter(class_studying="Form V", combination="PCB")
student_formset = formset_factory(AdvancedBiologyForm, extra=0)
initial = []
for element in formset_data:
initial.append({"student_name": element})
formset = student_formset(request.POST or None, initial=initial)
print(formset.is_valid())
context = {
"students": students_involved,
"formset": formset,
"class_of_students": "Form V",
"subject_name": "Advanced Biology",
}
return render(request, "analyzer/marks_entry/marks_entry_page.html", context)
这是我的 forms.py
class AdvancedBiologyForm(forms.ModelForm):
student_name = forms.CharField()
class Meta:
model = ResultsALevel
fields = ('student_name', 'advanced_biology_1', 'advanced_biology_2',
'advanced_biology_3',)
在使用 request.POST
和 is_valid()
之前,您可能需要检查是否确实存在 post 请求或是否刚刚查看了该页面:
def form_5_entry_biology_view(self, request):
current_teacher = User.objects.get(email=request.user.email)
logged_school = current_teacher.school_number
students_involved = User.objects.get(school_number=logged_school).teacher.all()
data = {"student_name": students_involved}
formset_data = AdvancedStudents.objects.filter(class_studying="Form V", combination="PCB")
# Here you are creating the formset using the model
student_formset = formset_factory(AdvancedBiologyForm, extra=0)
# Here you are generating your initial data
initial = []
for element in formset_data:
initial.append({"student_name": element})
# Here you are using the initial data to create pre-populated
# forms with it using the formset.
# These forms will be displayed when the page loads.
formset = student_formset(initial=initial)
context = {
"students": students_involved,
"formset": formset,
"class_of_students": "Form V",
"subject_name": "Advanced Biology",
}
# But if the user hits the "submit"-Button...
if request.method == 'POST':
# ... you don't want to have the formset with your
# initial data. Instead you want the entries by the user
# which are transmitted in request.POST to populate the
# formset forms.
formset = student_formset(request.POST or None)
# Now you can validate the formset with the fields which
# got input the the user; not the "initial" data like in
# your original code
if formset.is_valid():
# This runs formset validation.
# You can define your own formset validations like
# you would for models/forms.
for form in formset:
# And / Alternatively:
# you could in theory also add another "if form.is_valid():" in here
# This would trigger any validation on the
# model/form; not the validators on the formset.
form.save()
return HttpResponseRedirect(...
return render(request, "analyzer/marks_entry/marks_entry_page.html", context)
否则您可能会在未绑定的表单上调用 is_valid()
。
来自 Django docs:
If the form is submitted using a POST request, the view will once again create a form instance and populate it with data from the request: form = NameForm(request.POST) This is called “binding data to the form” (it is now a bound form).
基本上,如果一个表单是空的,它就是未绑定的,如果它填充了数据,它就会在 POST 之后绑定。当你打开一个页面并立即尝试“is_valid()”时,它基本上总是错误的,因为你正在检查一个空表单是否有效;它可能永远不会。
指出错误:
formset = student_formset(request.POST or None, initial=initial)
print(formset.is_valid())
这是无效的。因为初始值不等于用“真实”值填充表单字段。因此,它会尝试用 request.POST or None
填充表单中的字段。
但是您没有 if request.method == 'POST':
条件。因此,您的代码将 运行 通过,然后到达最后一行代码,即显示页面的 return 语句。
这意味着您的代码甚至在用户看到页面之前就验证了 request.POST or None
。因此,用户不可能已经输入数据并点击提交。这意味着没有 POST-请求,所以它总是变成 None
。因此,您基本上是在一个没有字段值的表单上调用 is_valid()
,这会导致验证失败。
编辑 1:我刚注意到你的 forms.py
你写了:
fields = ('student_name', 'advanced_biology_1', 'advanced_biology_2',
'advanced_biology_3',)
这个should be a list改为:
fields = ['student_name', 'advanced_biology_1', 'advanced_biology_2',
'advanced_biology_3',]
编辑 2:修复了错误的变量名 编辑 3:添加了广泛的评论以阐明代码中发生的事情 编辑 4:更清楚地指出问题的原因。