Django: ManagementForm 数据缺失... Formset 无法验证,为什么?
不知道为什么,我的表单组在提交后无法通过验证。有没有人知道这可能是什么原因呢?
#models.py
class Department(models.Model):
department = models.CharField(verbose_name = "Department Name", max_length=100)
description = models.TextField(verbose_name = "Description", blank=True, null=True)
sp_description = models.TextField(verbose_name = "Description (Spanish)", blank=True, null=True)
phone = PhoneNumberField()
phone_ext = models.CharField(max_length=10, blank=True)
#Relations
provider = models.ForeignKey(Provider, blank=True, null=True)
services_offered = models.ManyToManyField(ServiceType)
def __unicode__(self):
return self.department
#view.py
def display_step5(request):
msg = ''
email = request.session.get('email')
provider_obj = retrieve_provider_instance(email)
AddDepartmentFormSet = inlineformset_factory(Provider, Department, extra=0)
if is_authenticated(request):
AddDepartmentFormSet = inlineformset_factory(Provider, Department, extra=0)
if request.method=='POST':
if 'add_department' in request.POST:
cp = request.POST.copy()
cp['department-TOTAL_FORMS'] = int(cp['department-TOTAL_FORMS'])+ 1
new_department = AddDepartmentFormSet(cp, prefix='department', instance=provider_obj)
elif 'submit' in request.POST:
formset = AddDepartmentFormSet(request.POST, instance=provider_obj)
instances = formset.save(commit=False)
for instance in instances:
instance.provider = provider_obj
instance.save()
return HttpResponse("Departments have been added")
else:
new_department = AddDepartmentFormSet(prefix='department', instance=provider_obj)
else:
return HttpResponseRedirect(reverse('health.register.views.display_auth'))
return render_to_response('step5-test.html',
{'department': new_department}, context_instance=RequestContext(request))
step5-test.html
<form method='post' action='{{request.path}}'>{% csrf_token %}
<fieldset>
<legend>Departments</legend>
{{ department.management_form }}
{% for form in department.forms %}
<HR> <div><table>{{form.as_table}}</table></div>
{% endfor %}
<BR/>
<input title='Add a new department' type='submit' name='add_department' value='Add-Another-Department' />
</fieldset>
<BR/><BR/>
<input title='Submit this form' type='submit' name='submit' value='Submit' />
</form>
后续(解决方案):
Brant 提供了一些关于错误发生原因的见解。对我来说,他的建议帮助我找到了一种更适合我情况的解决方法。这种方法似乎适用于在模板中以某种方式修改过的表单组。在我的情况下,我的表单组变得复杂,需要一些 AJAX 技术来让用户使用起来更方便。
“retrieve_provider_instance(email)” 是一种根据数据库中设置的各种条件动态获取提供者对象的方法(大约有 200 行代码)。
经过大量调试,这个解决方法对我有效。我通过在模板的“for”循环中添加以下 隐藏字段 来解决这个问题。
{% {for form in formset.forms %}
<tr>
<td>
{% if form.instance.pk %} <!--- if instance already exists on db --->
{{ form.DELETE }}
<input type='hidden' name="department_set-{{ forloop.counter0 }}-id" id="id_department_set-{{ forloop.counter0 }}-id" value={{ form.instance.pk }} />
{% endif %}
Name: <br/> {{ form.department}} <br/>
Phone Number: <br/> {{ form.phone }} <br/>
Phone Ext: <br/> {{ form.phone_ext }}</td>
<td>Description: <br/> {{ form.description }}</td>
<td>Description (Spanish): <br/> {{ form.sp_description }}</td>
<td>Services Provided: <br/> {{ form.services_offered }}</td>
<td></td>
</tr>
{% endfor %}
我接受了 Mark 的回答,因为它更适合我提出的具体问题。希望这能帮助未来其他尝试实现这个例子的人。确实,在提交时分配 'prefix' 是正确的方法,也最有意义。
感谢大家的回复。
祝好,
Matt
后续:我想我可能找到了部分问题。但还没有完全解决。
这里有一些额外的信息,可能有助于解决问题。错误的 POST 数据会导致这个问题吗? 如果是的话,我该如何解决?
这是我提交表单组后发生的情况(在这个例子中只有一个表单):
错误追踪如下:
文件 "/home/mhjohnson/webapps/resourcedb/lib/python2.6/django/forms/formsets.py" 中的 _management_form 68. raise ValidationError('管理表单数据缺失或被篡改')
这是我的 POST 数据:
department-0-phone_ext -----> u'222'
department-0-id -----> u''
department-0-services_offered -----> u'2'
department-0-phone -----> u'222-222-2222'
department-INITIAL_FORMS -----> u'0'
submit -----> u'Submit'
department-MAX_NUM_FORMS -----> u''
department-0-department -----> u'Test 1'
department-0-provider -----> u''
department-TOTAL_FORMS -----> u'1'
csrfmiddlewaretoken -----> u'92a39322b16ed7e5e10dbd6c5ac64bf4'
department-0-description -----> u'Blah blah'
department-0-sp_description -----> u'....'
有什么想法吗?
2 个回答
有两件事让我注意到了...
首先,你不需要做这部分:
for instance in instances:
instance.provider = provider_obj
instance.save()
这部分在你做这个的时候就已经处理好了:
formset = AddDepartmentFormSet(request.POST, instance=provider_obj)
第二,你代码的开头部分:
provider_obj = retrieve_provider_instance(email)
可能没有正常工作。在你提供的错误追踪信息中,看起来提供者没有到达那里...
department-0-provider -----> u''
你的问题出在这里:
if request.method=='POST':
if 'add_department' in request.POST:
cp = request.POST.copy()
cp['department-TOTAL_FORMS'] = int(cp['department-TOTAL_FORMS'])+ 1
new_department = AddDepartmentFormSet(cp, prefix='department', instance=provider_obj)
elif 'submit' in request.POST:
formset = AddDepartmentFormSet(request.POST, instance=provider_obj)
instances = formset.save(commit=False)
for instance in instances:
instance.provider = provider_obj
instance.save()
return HttpResponse("Departments have been added")
else:
new_department = AddDepartmentFormSet(prefix='department', instance=provider_obj)
如果没有POST请求,你会传递一个前缀叫做'department'。如果POST请求中有'add_department',你也会传递'department'这个前缀。但是当POST请求中有'submit'时,你就没有传递这个前缀。没有前缀的话,表单集合就找不到正确的数据了。