python Django 表单集:首先需要制作?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2406537/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-04 00:35:08  来源:igfitidea点击:

Django formsets: make first required?

pythondjangodjango-forms

提问by mpen

These formsets are exhibiting exactly the oppositebehavior that I want.

这些表单集表现出我想要的完全相反的行为。

My view is set up like this:

我的观点是这样设置的:

def post(request): # TODO: handle vehicle formset
    VehicleFormSetFactory = formset_factory(VehicleForm, extra=1)
    if request.POST:
        vehicles_formset = VehicleFormSetFactory(request.POST)
    else:
        vehicles_formset = VehicleFormSetFactory()

And my template looks like this:

我的模板如下所示:

    <div id="vehicle_forms">
        {{ vehicles_formset.management_form }}
        {% for form in vehicles_formset.forms %}
            <h4>Vehicle {{forloop.counter}}</h4>
            <table>
                {% include "form.html" %}
            </table>
        {% endfor %}
    </div>

That way it initially generates only 1 form, like I want. But I want that one form to be required!

这样它最初只生成一种形式,就像我想要的那样。但我希望需要一种形式!

When I dynamically add blank forms with JavaScript and vehicles_formset.empty_formall those extra forms are required, which I don't want.

当我使用 JavaScript 动态添加空白表单时,vehicles_formset.empty_form所有这些额外的表单都是必需的,这是我不想要的。

From the docs:

从文档:

The formset is smart enough to ignore extra forms that were not changed.

表单集足够智能,可以忽略未更改的额外表单。

This is the behavior the first form is exhibiting (not what I want) but not the behavior that the extra forms are exhibiting (what I do want).

这是第一个表单展示的行为(不是我想要的),但不是额外表单展示的行为(我想要的)。

Is there some attribute I can can change to at least make oneform required?

是否有一些我可以更改的属性以至少使一个表单成为必需?

回答by mpen

Found a better solution:

找到了更好的解决方案:

class RequiredFormSet(BaseFormSet):
    def __init__(self, *args, **kwargs):
        super(RequiredFormSet, self).__init__(*args, **kwargs)
        for form in self.forms:
            form.empty_permitted = False

Then create your formset like this:

然后像这样创建你的表单集:

MyFormSet = formset_factory(MyForm, formset=RequiredFormSet)

I reallydon't know why this wasn't an option to begin with... but, whatever. It only took a few hours of my life to figure out.

真的不知道为什么这不是一个开始的选择……但是,无论如何。我只用了几个小时就搞清楚了。

This will make all the forms required. You could make just the first one required by setting self.forms[0].empty_permittedto False.

这将制作所需的所有表格。您可以通过设置self.forms[0].empty_permitted为 来制作所需的第一个False

回答by Anentropic

New in Django 1.7: you can specify this behaviour with your formset_factory

Django 1.7 中的新功能:您可以使用 formset_factory 指定此行为

https://docs.djangoproject.com/en/1.8/topics/forms/formsets/#validate-min

https://docs.djangoproject.com/en/1.8/topics/forms/formsets/#validate-min

VehicleFormSetFactory = formset_factory(VehicleForm, min_num=1, validate_min=True, extra=1)

回答by mpen

Well... this makes the first form required.

嗯...这需要第一个表格。

class RequiredFormSet(BaseFormSet):
    def clean(self):
        if any(self.errors):
            return
        if not self.forms[0].has_changed():
            raise forms.ValidationError('Please add at least one vehicle.') 

Only "problem" is that if there are 0 forms, then the cleanmethod doesn't seem to get called at all, so I don't know how to check if there are 0. Really...this should never happen though (except that my JS has a bug in it, allowing you to remove allthe forms).

唯一的“问题”是,如果有 0 个表单,那么该clean方法似乎根本没有被调用,所以我不知道如何检查是否有 0 个。真的……这应该永远不会发生(除了我的 JS 中有一个错误,允许您删除所有表单)。

回答by Wogan

Oh I think I see. Try this:

哦,我想我明白了。试试这个:

from django.forms.formsets import BaseFormSet, formset_factory
class OneExtraRequiredFormSet(BaseFormSet):
    def initial_form_count(self):
        return max(super(OneExtraRequiredFormSet,self).initial_form_count() - 1,0)

VehicleFormSetFactory = formset_factory(VehicleForm, formset=OneExtraRequiredFormSet, extra=1)

== Original answer below ==

==下面的原始答案==

When you say "at least make one form required", I assume you mean "make only one extra form required, regardless of how many have been added via javascript".

当您说“至少需要一个表单”时,我假设您的意思是“只需要一个额外的表单,无论通过 javascript 添加了多少表单”。

You will need to have hidden input on your page which contains the number of forms that have been added via javascript, and then use that number, minus 1, as the value to pass in as the extraattribute to your formsets constructor.

您需要在页面上隐藏输入,其中包含通过 javascript 添加的表单数量,然后使用该数字减去 1 作为值作为extra属性传递给您的表单集构造函数。