【问题标题】:How to validate a formset in dajngo如何在 django 中验证表单集
【发布时间】:2021-09-19 18:57:49
【问题描述】:

我正在使用 formset 将我的数据输入到数据库中,但由于某种原因,它无法验证,每当我在终端中测试并调用 .is_valid() 时,无论我尝试什么,它都会返回 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',)

【问题讨论】:

  • 好吧,在运行.is_valid() 之后,你可能也想print(formset.errors)...

标签: python django validation formset


【解决方案1】:

在使用request.POSTis_valid() 之前,您可能想检查是否确实存在发布请求或者是否刚刚查看了页面:

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

如果表单是使用 POST 请求提交的,视图将再次创建一个表单实例并使用请求中的数据填充它: form = NameForm(request.POST) 这称为“将数据绑定到表单”(它现在是绑定形式)。

基本上,如果一个表单是空的,它是未绑定的,如果它填充了数据,它会在 POST 之后被绑定。当您打开一个页面并立即尝试“is_valid()”时,它基本上总是错误的,因为您正在检查一个空表单是否有效;它可能永远不会。

指出错误:

formset = student_formset(request.POST or None, initial=initial)
print(formset.is_valid())

这是无效的。因为初始值不等于用“真实”值填充表单字段。因此,它会尝试使用request.POST or None 填充表单中的字段。 但是您没有if request.method == 'POST': 条件。因此,您的代码将在到达最后一行代码(即显示页面的返回语句)之前运行。 这意味着您的代码在用户看到页面之前验证了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:添加了广泛的 cmets 以阐明代码中发生的情况 编辑 4:更清楚地指出问题的原因。

【讨论】:

  • 如果 student_form.is_valid(): for form in student_form: 你指的是什么?
  • @Raxan7 很抱歉造成混乱,我的错。它的意思是“formset”而不是“student_form”。不知道我是怎么想出这个错误的名字的。我相应地编辑了代码。
猜你喜欢
  • 2016-03-15
  • 1970-01-01
  • 1970-01-01
  • 2013-04-01
  • 2022-06-13
  • 1970-01-01
  • 1970-01-01
  • 2017-11-28
  • 1970-01-01
相关资源
最近更新 更多