为什么我的django formset需要指针字段引用?
没有什么比不理解为什么有效。几天前我问了这个问题,并找出了一个修复方法,但我不知道它为什么有效:为什么我的django formset需要指针字段引用?
How to debug a Django MultiValueDictKeyError on Formset POST。
为什么formset需要指向formset模型表单模型超类的指针字段引用?我有其他的表单就像这样,没有。
为了使这个独立的问题,下面是详细信息:
当我发表我的表单集,我得到一个MultiValueDictKeyError。具体做法是:
MultiValueDictKeyError at /core/customers/1/update/documents/
"Key u'documents-0-attachment_ptr' not found in <QueryDict: {u'documents-1-last_modified_date': [u''], u'documents-1-name': [u''], u'documents-MAX_NUM_FORMS': [u''], u'documents-0-attachment_file': [u''], u'documents-INITIAL_FORMS': [u'1'], u'documents-1-document_type': [u''], u'documents-0-notes': [u''], u'documents-1-notes': [u''], u'submit': [u'Submit changes'], u'documents-0-DELETE': [u'on'], u'documents-1-attachment_file': [u''], u'documents-0-document_type': [u''], u'documents-TOTAL_FORMS': [u'2'], u'documents-0-name': [u'test'], u'documents-1-creation_date': [u''], u'documents-0-creation_date': [u'2012-12-01 23:41:48'], u'csrfmiddlewaretoken': [u'NCQ15jA7erX5dAbx20Scr3gWxgaTn3Iq', u'NCQ15jA7erX5dAbx20Scr3gWxgaTn3Iq', u'NCQ15jA7erX5dAbx20Scr3gWxgaTn3Iq'], u'documents-0-last_modified_date': [u'2012-12-01 23:41:48']}>"
的关键部分是,Django是寻找后数据的密钥documents-0-attachment_ptr
。这很令人困惑 - 一个Document是Attachment的子类。所有其他的帖子数据如预期。为什么Django需要我的formset中的指针数据?
这里是该formset使用的形式:
class DocumentInlineForm(forms.ModelForm): # pylint: disable=R0924
attachment_file = forms.FileField(widget=NoDirectoryClearableFileInput)
notes = forms.CharField(
required=False,
widget=forms.Textarea(attrs={'rows': 2,}),
)
helper = DocumentInlineFormHelper()
class Meta: # pylint: disable=W0232,R0903
fields = (
'attachment_file',
'creation_date',
'document_type',
'last_modified_date',
'name',
'notes',
)
model = Document
这里是文档模型:
"""
Handles document model definitions.
"""
from django.db import models
from eee_core.models.attachments import Attachment
from django.db.models.signals import pre_save
from datetime import datetime
from django.utils.timezone import utc
class Document(Attachment):
"""
A document is an attachment with additional meta data.
"""
creation_date = models.DateTimeField(
blank=True,
null=True,
)
document_type = models.CharField(
blank=True,
choices=(
('CONTRACT', 'Contract'),
('INVOICE', 'Invoice'),
('FACILITY', 'Facility change form'),
('LOA', 'Letter of authorization'),
('USAGE', 'Usage history document'),
('OTHER', 'Other'),
),
default=None,
null=True,
max_length=8,
)
last_modified_date = models.DateTimeField(
blank=True,
null=True,
)
notes = models.TextField(
blank=True,
null=True,
)
class Meta(Attachment.Meta): # pylint: disable=W0232,R0903
"""
Sets meta fields for model.
"""
app_label = 'core'
def __str__(self):
return unicode(self).encode('utf-8')
def __unicode__(self):
return unicode(self.name)
def pre_save_callback(sender, instance, *args, **kwargs): # pylint: disable=W0613
if not isinstance(instance, Document):
return
if not instance.creation_date:
instance.creation_date = datetime.utcnow().replace(tzinfo=utc)
instance.last_modified_date = datetime.utcnow().replace(tzinfo=utc)
pre_save.connect(pre_save_callback, dispatch_uid='document_pre_save')
附加信息:
奇怪的是,的的inital后formset工作正常。只有在更新文章中 - 当formset中有初始表单时 - 当我收到此错误时。当我尝试从formset中删除表单时也会发生这种情况。
另外,formset是一个使用django香脆形式的通用内联formset。
更新
有对所使用的模板代码的请求。下面是简化版本:
{% load crispy_forms_tags %}
{% load url from future %}
<form action="" method="post" enctype="multipart/form-data">
{{ formset.management_form }}
{% for subform in formset.forms %}
{{ subform.id }}
{% crispy subform %}
{% endfor %}
<div class="btn-toolbar">
<input class='btn btn-primary' type="submit" name="submit" value="Submit changes" />
</div>
</form>
我加入attachment_ptr
到我的窗体的字段列表停止了这个错误。所以DocumentInlineForm
现在是:
class DocumentInlineForm(forms.ModelForm): # pylint: disable=R0924
attachment_file = forms.FileField(widget=NoDirectoryClearableFileInput)
notes = forms.CharField(
required=False,
widget=forms.Textarea(attrs={'rows': 2,}),
)
helper = DocumentInlineFormHelper()
class Meta: # pylint: disable=W0232,R0903
fields = (
'attachment_ptr',
'attachment_file',
'creation_date',
'document_type',
'last_modified_date',
'name',
'notes',
)
model = Document
也许这是我之前不知道,但是Django的要求您提供一个指向超类中使用一个子类的模型一切形式的?这让我感到惊讶。
不要忘记,非抽象模型的子类实际上只是两个模型之间的一对一关系。所以很自然Django需要某种形式的从一个到另一个的指针,否则它不可能知道子表更改时父表中的哪一行要更新。
而且,由于我的其他案例是抽象模型的子类,因此您的答案解释了我所看到的内容。谢谢!这不是一个问题,因为我现在必须包含在表单中的_ptr字段可以被恶意帖子改变吗? – Erik