如何在 Django 中根据需要为 formset_factory 设置每个字段(如何验证表单集中的空白表单)

Posted

技术标签:

【中文标题】如何在 Django 中根据需要为 formset_factory 设置每个字段(如何验证表单集中的空白表单)【英文标题】:How to set each field as required for formset_factory in Django (how to validate blank forms in formsets) 【发布时间】:2020-06-07 03:55:52 【问题描述】:

我的 forms.py 中有表单:

class NameForm(forms.Form):
    your_name = forms.CharField(label='Your name', max_length=100)
    age = forms.CharField(label='Age', max_length=100)
    sex = forms.CharField(label='Sex', max_length=100)

我创建了 formset_factory

NameFormSet = formset_factory(NameForm, extra=0)

在获取 context_data 的 views.py 中,我有:

...
def get_context_data(self, **kwargs):
        context = super(APView, self).get_context_data(**kwargs)
        if self.request.POST:
            context['formset'] = NameFormSet()
        else:
            recommended = returnWebAttackResults(self.kwargs['webAttack'])
            if recommended is None:
                context['recommendedAP'] = False
            else:
                context['formset'] = NameFormSet(initial=recommended[0])
                return context
....

在我的模板文件中,我有:

<form class="row" method="POST" enctype="multipart/form-data">
        % csrf_token %
         formset.management_form 
         formset.non_form_errors 
             % for forma in formset.forms %
                   forma 
             % endfor %
        <input class="btn bg-success" type="submit" value="Update" />
 </form>

我的问题是当我单击“更新”按钮时,我没有得到“此字段是必需的”。我尝试将 use_required_attribute 设置为 True,但没有成功。

场景:

returnWebAttackResults 函数获取表单集中表单的初始数据。因此,如果我有三个表单,如果任何表单中的一个字段为空白(无用户输入),那么当我单击更新按钮时,每个空白字段都应突出显示“此字段是必需的” .我只渲染常规表单时可以这样做,但是当我使用表单集时,它不起作用。

有没有办法在发送请求之前验证表单集中的表单?

【问题讨论】:

【参考方案1】:

我遇到了同样的问题,并在文档中找到了这个

https://docs.djangoproject.com/en/3.0/ref/forms/fields/#core-field-arguments

必需表单字段的小部件具有必需的 html 属性。将 Form.use_required_attribute 属性设置为 False 以禁用它。表单集的表单中不包含 required 属性,因为添加和删除表单集时浏览器验证可能不正确。

如果您有一个空行(用于添加额外记录),则在填写空行之前您无法保存表单。因此,如果您想说更新一个现有行而不添加额外行,那么您有问题,你做不到。问题实际上来自这样一个事实,即表单集实际上在 html 术语中只是一个表单。该问题的解决方法可能是仅在需要时使用 javascript 将行添加到表单集,如下例所示:

https://whoisnicoleharris.com/2015/01/06/implementing-django-formsets.html

可能还有一个javascript解决方案可以在您发送请求之前验证表单字段,我认为这可能是这样的解决方案,但我还没有尝试过:

https://jqueryvalidation.org/required-method/

不应该为必填字段验证完全空的行,而是完全忽略它是有道理的。

更新:我从上面链接中的示例中得到了一个简单的解决方案。我的模板看起来像这样(请注意,由于 if 语句,最初没有显示空行):

% extends "base_generic.html" %

% load static %

% block content %
    <h1>Experiment Detail</h1>

    <form name="test_form" method="post">
        % csrf_token %
         formset.management_form 

        % for form in formset %
        % if form.name.value %
        <div class="link-formset">
             form.name 
        </div>
        % endif %
        % endfor %

        <input type="submit" value="Save" class="button"/>
    </form>

    <!-- Include formset plugin - including jQuery dependency -->
    <!-- <script src="% static 'path_to/jquery-3.4.1.js' %"></script> -->
    <script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
    <script src="% static 'js/jquery_formset.js' %"></script>
    <script>
        $('.link-formset').formset(
            addText: 'Add',
            deleteText: 'Delete'
        );
    </script>

% endblock %

在我看来,我有这个 for 循环来设置 use_required_attribute:

for form in formSet:

    form.use_required_attribute = True

解决方案似乎工作正常,当我单击“添加”按钮时,会出现一个空行,并且空的“名称”字段在空字段周围有预期的红色框,当我尝试单击“保存”时,我收到消息“请填写走出这个领域。'

【讨论】:

以上是关于如何在 Django 中根据需要为 formset_factory 设置每个字段(如何验证表单集中的空白表单)的主要内容,如果未能解决你的问题,请参考以下文章

Django - 基数为 10 的 int() 的 Formset 无效文字:''

与 django-dynamic-formset 一起使用的 Django Formset 不显示删除链接

访问django formset数据

Django 和 jQuery.formset,如何操作删除按钮位置

django InlineFormsets错误报告,其中formset错误列表为空

Django:如何使用 formset extra 更改标签?