Django 和空表单集有效

发布于 2024-10-08 11:11:39 字数 569 浏览 2 评论 0原文

我的表单集有一点问题。

我必须在一个页面中显示多个表单集,每个表单集又包含多个表单。 所以我做了类似的事情:

#GET
for prod in products:
     ProductFormSet = modelformset_factory(Product,exclude=('date',),extra=prod.amount)
     formsset.append(ProductFormSet(prefix="prod_%d"%prod.pk))

#POST
for prod in products:
     ProductFormSet = modelformset_factory(Product,exclude=('date',),extra=prod.amount)
     formsset.append(ProductFormSet(request.POST,prefix="prod_%d"%prod.pk))

问题是当我提交页面时,空表格“自动”有效(无需检查), 但如果我在一张表格中填写一个字段,支票就会对其起作用。

我不知道为什么,所以如果有人有想法,

谢谢。

I have a little problem with the formset.

I must display several formsets in a page, and each formset has several forms.
So i did something like that :

#GET
for prod in products:
     ProductFormSet = modelformset_factory(Product,exclude=('date',),extra=prod.amount)
     formsset.append(ProductFormSet(prefix="prod_%d"%prod.pk))

#POST
for prod in products:
     ProductFormSet = modelformset_factory(Product,exclude=('date',),extra=prod.amount)
     formsset.append(ProductFormSet(request.POST,prefix="prod_%d"%prod.pk))

The problem is when I submit the page, the empties forms are 'automatically' valid (without check),
but if I fill one field in one form, the check works on it.

I don't know why, so if anyone has an idea,

thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

久伴你 2024-10-15 11:11:39

我在研究另一个问题时遇到了这个问题。在深入研究 Django 源代码以寻找问题的解决方案时,我找到了这个问题的答案,因此我将在此处记录它:

当允许表单具有空值时(这适用于表单集中包含的空表单) 并且提交的值与初始值相比没有改变,验证被跳过。检查 django/forms/forms.py 中的 full_clean() 方法(Django 1.2 中的第 265 行):

# If the form is permitted to be empty, and none of the form data has
# changed from the initial data, short circuit any validation.
if self.empty_permitted and not self.has_changed():
     return

我不确定您正在寻找什么样的解决方案(而且,这个问题已经有些过时了),但也许这会将来帮助某人。

I ran into this question while researching another problem. While digging through the Django source in search of a solution for my problem, I found the answer to this question so I'll document it here:

When a form is allowed to have empty values (this applies for empty forms contained within a formset) and the submitted values haven't been changed from the initial ones, the validation is skipped. Check the full_clean() method in django/forms/forms.py (line 265 in Django 1.2):

# If the form is permitted to be empty, and none of the form data has
# changed from the initial data, short circuit any validation.
if self.empty_permitted and not self.has_changed():
     return

I'm not sure what kind of solution you're looking for (also, this question is already somewhat dated) but maybe this will help someone in the future.

↘人皮目录ツ 2024-10-15 11:11:39

@乔纳斯,谢谢。我用你的描述来解决我的问题。我需要一个表格,以便在空时不进行验证。 (使用 javascript 添加的表单)

class FacilityForm(forms.ModelForm):
    class Meta:
        model = Facility

    def __init__(self, *arg, **kwarg):
        super(FacilityForm, self).__init__(*arg, **kwarg)
        self.empty_permitted = False


 facility_formset = modelformset_factory(Facility, form=FacilityForm)(request.POST)

它将确保提交时显示的任何表单都不能为空。

@Jonas, thanks. I used your description to solve my problem. I needed the a form to NOT validate when empty. (Forms added with javascript)

class FacilityForm(forms.ModelForm):
    class Meta:
        model = Facility

    def __init__(self, *arg, **kwarg):
        super(FacilityForm, self).__init__(*arg, **kwarg)
        self.empty_permitted = False


 facility_formset = modelformset_factory(Facility, form=FacilityForm)(request.POST)

It will make sure any displayed forms must not be empty when submitted.

溺ぐ爱和你が 2024-10-15 11:11:39

基于“formset_factory”的“extra”参数创建的表单将其“empty_permissed”属性设置为True。 (参见:formset.py第123行)

# Allow extra forms to be empty.
    if i >= self.initial_form_count():
        defaults['empty_permitted'] = True

因此,对于此用例,使用FormSet的“初始”参数而不是“formset_factory”的“额外”参数似乎是更好的方法。

请在 使用-带有表单集的初始数据

The forms created based on the "extra" parameter of "formset_factory" have their "empty_permitted" property set to True. (see: formset.py line 123)

# Allow extra forms to be empty.
    if i >= self.initial_form_count():
        defaults['empty_permitted'] = True

So it seems the better way to use "initial" parameter of the FormSet and not the "extra" parameter of "formset_factory" for this use case.

Please find the description at using-initial-data-with-a-formset

不气馁 2024-10-15 11:11:39

简单更好。由于表单集是表单列表,因此您可以迭代该集合。

if FormSet(request.POST,).is_valid():
    for form in FormSet:
        # Check if value is empty using value().
        if form['field'].value():
            # this form's field is not empty. Create and save object.
            object = form.save()

Simple is better. Due a Formset is a list of forms, you could iterate this set.

if FormSet(request.POST,).is_valid():
    for form in FormSet:
        # Check if value is empty using value().
        if form['field'].value():
            # this form's field is not empty. Create and save object.
            object = form.save()
野侃 2024-10-15 11:11:39

我不确定 OP 使用的是哪个版本的 Django,但这个答案适用于 Django 4.1。

@乔纳斯是对的;默认情况下,对空表单集执行很少的验证。您可以通过传递form_kwargs = {'empty_permissed': False}来解决这个问题,但这可能会导致其他问题(例如,这会阻止模板引擎创建使用 {{ formset.empty_form }} 标签与 javascript 一起使用的空白表单

,我认为更好的解决方案是添加最小表单编号验证。 :

#GET
for prod in products:
    ProductFormSet = modelformset_factory(
        Product,
        exclude=('date',),
        extra=prod.amount,
        min_num = 1, # This means that there must be at least 1 form.
        validate_min = True, # This tells the formset validation to check min_num.
    )
     formsset.append(ProductFormSet(prefix="prod_%d"%prod.pk))

#POST
for prod in products:
    ProductFormSet = modelformset_factory(
        Product,
        exclude=('date',),
        extra=prod.amount,
        min_num = 1, # This means that there must be at least 1 form.
        validate_min = True, # This tells the formset validation to check
    )
     formsset.append(ProductFormSet(request.POST,prefix="prod_%d"%prod.pk))

如果没有至少一个表单发生更改,则表单验证将根据需要失败。

I'm not sure what version of Django the OP was using, but this answer works for Django 4.1.

@Jonas is right; very little validation is performed on an empty formset by default. You could solve this by passing form_kwargs = {'empty_permitted': False}, but that can cause other problems (for example, this prevents the template engine from being able to create a blank form for use with javascript using the {{ formset.empty_form }} tag.

Depending on your use case, I think a better solution is to add a minimum form number validation. So OP's view would include:

#GET
for prod in products:
    ProductFormSet = modelformset_factory(
        Product,
        exclude=('date',),
        extra=prod.amount,
        min_num = 1, # This means that there must be at least 1 form.
        validate_min = True, # This tells the formset validation to check min_num.
    )
     formsset.append(ProductFormSet(prefix="prod_%d"%prod.pk))

#POST
for prod in products:
    ProductFormSet = modelformset_factory(
        Product,
        exclude=('date',),
        extra=prod.amount,
        min_num = 1, # This means that there must be at least 1 form.
        validate_min = True, # This tells the formset validation to check
    )
     formsset.append(ProductFormSet(request.POST,prefix="prod_%d"%prod.pk))

If there isn't at least one form that has changed, the form validation will fail as desired.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文