使用表单集前缀时缺少ManagementForm数据

2024-05-19 11:30:29 发布

您现在位置:Python中文网/ 问答频道 /正文

有人知道为什么我使用Formset前缀时会丢失管理表单数据吗?在

从壳牌公司

>>> from django import forms
>>> from django.forms.formsets import formset_factory
>>> 
>>> class CheckBox (forms.Form):
...     overwrite = forms.BooleanField (required = False)
... 
>>> 
>>> data = {
...     'form-TOTAL_FORMS': '2',
...     'form-INITIAL_FORMS': '0',
...     'form-MAX_NUM_FORMS': '3',
...     'checkbox-0-overwrite': True,
...     'checkbox-1-overwrite': False,
... }
>>> 
>>> CheckBoxFormSet = formset_factory (CheckBox)
>>> formset = CheckBoxFormSet (data)
>>> formset.is_valid ()
True
>>> formset.cleaned_data
[{}, {}]
>>> 

向表单集添加前缀

^{pr2}$

Django Doc提到使用前缀来区分“a”视图中的不同表单集。如果我在同一个视图中使用它,但在处理不同HTML页面的不同方法(如示例所示)中,这适用吗?执行Django在示例中建议的操作也会触发ManagementForm Data is Missing Error。在

例如:

在表单.py在

class NodeForm (forms.Form):

    cars = forms.CharField (required = False)
    trucks = forms.CharField (required = False)

class CheckBox (forms.Form):
    overwrite = forms.BooleanField (required = False)

在视图.py在

def cars (request):

    CarsFormSet = formset_factory (CarsForm, formset = BaseNodeFormSet, extra = 2, max_num = 5)

    if request.method == 'POST':

        cars_formset = CarsFormSet (request.POST, prefix = 'carsform')

        if cars_formset.is_valid ():
            data = cars_formset.cleaned_data

            context = {'data': data}
            return render (request, 'vehicleform/response.html', context)
        else:
            cars_formset = CarsFormSet (prefix = 'carsform')

     context = {...previously entered data from POST...}

     return render (request, 'vehicleform/carsform.html', context)

def trucks (request):

    TrucksFormSet = formset_factory (TrucksForm, extra = 2, max_num = 5)

    if request.method == 'POST':

        trucks_formset = TrucksFormSet (request.POST, prefix = 'trucksform')

        if trucks_formset.is_valid ():
            data = truck_formset.cleaned_data

            context = {'data': data}
            return render (request, 'vehicleform/success.html', context)

        else:
            trucks_formset = TrucksFormSet (prefix = 'trucksform')

     return HttpResponse ('No overwrite data.')

更新1
我把范围缩小到实际数据。因为某些原因它不喜欢我的数据。在

更新2
我已经核实了表格中的名字和数据是一致的。当我在数据中声明2时,它只打印一个checkbox-0-overwrite。不知道为什么formset不适用于checkbox。在

>>> CheckBoxFormSet = formset_factory (CheckBox)
>>> formset = CheckBoxFormSet (prefix = 'checkbox')
>>> 
>>> for form in formset:
...     print (form)
... 
<tr><th><label for="id_checkbox-0-overwrite">Overwrite:</label></th><td><input id="id_checkbox-0-overwrite" name="checkbox-0-overwrite" type="checkbox" /></td></tr>
>>> 

更新3
我不知道到底发生了什么。这似乎生成了没有前缀的表单。在我插入前缀的那一刻仍然得到错误。在

>>> CheckBoxFormSet = formset_factory (CheckBox)
>>> formset = CheckBoxFormSet (data)
>>> formset.is_valid ()
True
>>> for form in formset:
...     print (form)
... 
<tr><th><label for="id_form-0-overwrite">Overwrite:</label></th><td><input id="id_form-0-overwrite" name="form-0-overwrite" type="checkbox" /></td></tr>
<tr><th><label for="id_form-1-overwrite">Overwrite:</label></th><td><input id="id_form-1-overwrite" name="form-1-overwrite" type="checkbox" /></td></tr>
>>> 
>>> 
>>> data {
...    'form-TOTAL_FORMS': '2',
...    'form-INITIAL_FORMS': '0',
...    'form-MAX_NUM_FORMS': '3',
...    'checkbox-0-overwrite': True
}

更新4
下面的html模板是由第一个表单cars生成和创建的,正如我从上面的示例中更新的一样。第二个窗体,它只在第一个窗体传递的数据旁边插入复选框。在模板中显示表单集并单击Submit仍然会出现“ManagementForm”错误。我将尝试创建一个只有复选框的全新表单,看看这是否会给我带来任何错误。在

在响应.html在

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/html">
<head lang="en">
    <meta charset="UTF-8">
    {% load staticfiles %}
    <link rel="stylesheet" type="text/css" href="{% static 'nodeform/style.css' %}" >
    <title>Vehicle Information</title>
</head>
<body>
    <h1>Vehicle Information:</h1>
    <h4>Location: {{ location }}</h4>
    <form action="trucks" method="POST">{% csrf_token %}
    {{ checkbox_formset.management_form }}
       {% for form in checkbox_formset %}
        {{ form }}
       {% endfor %}
    <br>
    <p><input type="submit" value="Confirm">
    <a href="{% url 'carsform' %}">
        <button type="button">Cancel</button></a></p>
    </form>
</body>
</html>

更新5
我不确定我是否理解正确,但我认为失败是在表单的操作以及我如何获得数据的范围内。初始形式(carsform.html)表单标记没有操作:

在carsform.html在

<form action="" method="POST">{% csrf_token %}...</form>

它执行POST,然后将收集到的信息传递到下一页/表单(响应.html). 此外,它会将一组复选框添加到以前的数据中,如下所示:

在响应.html在

<form action="trucks" method="POST">{% csrf_token %}...</form>

输出:

Audi (Obtained from cars)    []  <---Checkbox inserted from response.html manually & obtaining data from method trucks
Toyota (Obtained from cars)  []  <---Checkbox inserted from response.html manually & obtaining data from method trucks

当用户点击“提交”时响应.html然后,form将进行处理,并再次“反转”回卡车。这一次没有从cars方法处理数据。这最终引发了ManagementForm错误。在

我通过在初始页面中插入2个表单集来测试这一点(carsform.html)然后单击提交。我在下一页/表格上看到的结果(响应.html)包含第一个和第二个窗体集的数据。在

我的下一个问题是如何创建第二个表单(响应.html)要获得没有错误的数据?在


Tags: 数据fromformid表单datarequesthtml
2条回答

问题是方法cars渲染到响应.html页面并在url http://..../vehicle/cars处显示呈现的表单,而不是vehicle/trucks。“管理表单错误”是因为“POST”第二次出现,而仍然是url vehicle/cars表单,而不是vehicle/trucks表单。更新5暗示了问题。解决方法是简单地使用

return HttpResponseRedirect ('trucks')

或者

^{pr2}$

上面两种方法的区别在于第一种解决方案呈现第二种形式(trucksform)中的数据,而第二种解决方案呈现第一种形式(carsform)中的数据。在

为什么这是一件大事?因为我希望第一个表单在出现错误时不重定向到另一个页面而重新显示自己;因此

<form action="" method="POST">

否则,设置

<form action="truck" method="POST">

不会造成这样的混乱。在

为了能够在一个视图中使用2个不同的表单集,可以通过转到每个页面/表单的直接URL分别测试每个页面/表单。一旦确认页面是否按预期呈现和工作,就使用HttpResponseRedirect。在

感谢onyeka一路走来的帮助。在

根据docs

It is important to point out that you need to pass prefix on both the POST and non-POST cases so that it is rendered and processed correctly.

这样,首先,在呈现空白表单时(即不是POST),您将得到:

trucks_formset = TrucksFormSet(prefix ='trucksform')

另外,您的“data”以前缀失败,因为您没有更改数据中字段的名称。前缀重命名字段。您可以尝试将表单集发布到模板中,您将看到隐藏字段的名称。在

^{pr2}$

相关问题 更多 >

    热门问题