Buc*_*uck 3 django django-forms django-views
我想通过以下提供的示例来创建嵌套表单:
http://yergler.net/blog/2009/09/27/nested-formsets-with-django/
此页面上的教程似乎非常好&&它正在尝试解决我遇到的确切问题。
当没有 POST 请求数据(即我们从数据库执行初始填充)时,views.py 文件中的此实现似乎存在问题。
代码可以在上面提供的 URL 中看到(如果需要,我可以发布一些代码,但我担心它会影响这里提供的信息)。
这是失败的 views.py 代码(以粗体显示):
block = get_object_or_404(models.Block, id=block_id)
if request.method == 'POST':
formset = forms.BuildingFormset(request.POST, instance=block)
if formset.is_valid():
rooms = formset.save_all()
return redirect('block_view', block_id=block.id)
else:
formset = forms.BuildingFormset(instance=block) #This is the line that is throwing the ValidationError
Run Code Online (Sandbox Code Playgroud)
我收到的错误消息是:
ValidationError at "urlName":
[u'ManagementForm data is missing or has been tampered with']
Run Code Online (Sandbox Code Playgroud)
我已经挖得更深了,看来这个失败发生在 site-packages/django/forms/formsets.py 行
该is_valid()检查失败,因为一些managementform所需的数据(形状TOTAL_FORMS的,形状和INITIAL_FORMS形状MAX_NUM_FORMS)是无效的。下面是 self.errors 的实际输出:
{u'TOTAL_FORMS': [u'This field is required.'], u'INITIAL_FORMS': [u'This field is required.']}
Run Code Online (Sandbox Code Playgroud)
edit_building.html:
{{buildings.management_form }}
{% 用于在buildings.forms 中构建%}
Run Code Online (Sandbox Code Playgroud){{ building }} {% if building.nested %} {% for formset in building.nested %} {{ formset.as_table }} {% endfor %} {% endif %}{% 结束为 %}
视图.py:
def should_delete(self, form):
"""Convenience method for determining if the form’s object will
be deleted; cribbed from BaseModelFormSet.save_existing_objects."""
if self.can_delete:
raw_delete_value = form._raw_value(DELETION_FIELD_NAME)
should_delete = form.fields[DELETION_FIELD_NAME].clean(raw_delete_value)
return should_delete
return False
def save_all(self, commit=True):
"""Save all formsets and along with their nested formsets."""
# Save without committing (so self.saved_forms is populated)
# — We need self.saved_forms so we can go back and access
# the nested formsets
objects = self.save(commit=False)
# Save each instance if commit=True
if commit:
for o in objects:
o.save()
# save many to many fields if needed
if not commit:
self.save_m2m()
# save the nested formsets
for form in set(self.initial_forms + self.saved_forms):
if self.should_delete(form): continue
for nested in form.nested:
nested.save(commit=commit)
Run Code Online (Sandbox Code Playgroud)
表格.py:
def should_delete(self, form):
"""Convenience method for determining if the form’s object will
be deleted; cribbed from BaseModelFormSet.save_existing_objects."""
if self.can_delete:
raw_delete_value = form._raw_value(DELETION_FIELD_NAME)
should_delete = form.fields[DELETION_FIELD_NAME].clean(raw_delete_value)
return should_delete
return False
def save_all(self, commit=True):
"""Save all formsets and along with their nested formsets."""
# Save without committing (so self.saved_forms is populated)
# — We need self.saved_forms so we can go back and access
# the nested formsets
objects = self.save(commit=False)
# Save each instance if commit=True
if commit:
for o in objects:
o.save()
# save many to many fields if needed
if not commit:
self.save_m2m()
# save the nested formsets
for form in set(self.initial_forms + self.saved_forms):
if self.should_delete(form): continue
for nested in form.nested:
nested.save(commit=commit)
Run Code Online (Sandbox Code Playgroud)
我已经查看了https://docs.djangoproject.com/en/dev/topics/forms/formsets/#understanding-the-managementform 上的 django 文档,但没有找到任何有用的内容来讨论如何自动填充这些值由 DJANGO
我正在使用 Django V1.5
如果没有 POST 数据并且表单仅从数据库生成,那么应该如何正确填写 'form-TOTAL_FORMS' && 'form-INITIAL_FORMS' 数据以解决此故障?
更新:
在查看您提供的示例forms.py后,add_fields()方法末尾有一个片段,内容如下:
# store the formset in the .nested property
form.nested = [
TenantFormset(data = self.data,
instance = instance,
prefix = 'TENANTS_%s' % pk_value)
]
Run Code Online (Sandbox Code Playgroud)
该data参数导致问题,因为它最初是空的,并且在内部 Django 将确定表单是否受与此类似的条件约束:
self.is_bound = data is not None
# Example
>>> my_data = {}
>>> my_data is not None
True
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,Python 中的空字典不是 None,因此即使不是,您TenantFormset也被视为bound表单。您可以使用以下内容修复它:
# store the formset in the .nested property
form.nested = [
TenantFormset(data = self.data if any(self.data) else None,
instance = instance,
prefix = 'TENANTS_%s' % pk_value)
]
Run Code Online (Sandbox Code Playgroud)
您可以发布视图和表单代码以及表单的模板代码吗?
我的猜测是您没有在模板中使用“management_form”(它添加了您缺少的“form-TOTAL_FORMS”和“form-INITIAL_FORMS”字段),即
<form method="post">
{{ formset.management_form }}
<table>
{% for form in formset %}
{{ form }}
{% endfor %}
</table>
</form>
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
5286 次 |
| 最近记录: |