如何在Formset POST上调试Django MultiValueDictKeyError

Eri*_*rik 16 django django-forms

当我发布我的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']}>"
Run Code Online (Sandbox Code Playgroud)

关键部分是Django正在寻找documents-0-attachment_ptr后期数据的关键.这很令人困惑 - Document是附件的子类.所有其他发布数据都符合预期.为什么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
Run Code Online (Sandbox Code Playgroud)

这是文档模型:

"""
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')
Run Code Online (Sandbox Code Playgroud)

附加信息:

奇怪的是,formset的初始帖子工作得很好.它仅在更新帖子上 - 当formset中有初始表单时 - 当我收到此错误时.当我尝试从formset中删除表单时也会发生这种情况.

此外,formset是使用django crispy形式的通用内联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>
Run Code Online (Sandbox Code Playgroud)

mp3*_*415 49

OP不是这种情况,但MultiValueDictKeyError如果模板中缺少某些隐藏字段,则会遇到a .它可能发生时,而不是快速和肮脏的{{form}},字段在模板中一一列出:{{form.field1}},{{form.field2}},同时留出所需的隐藏字段.

要包含它们,请执行以下操作(对于formset中的每个表单/表单):

{% for hidden in form.hidden_fields %}
    {{ hidden }}
{% endfor %}
Run Code Online (Sandbox Code Playgroud)

要么

{% for form in formset %}    
    {% for hidden in form.hidden_fields %}
        {{ hidden }}
    {% endfor %}    
{% endfor %}
Run Code Online (Sandbox Code Playgroud)


Eri*_*rik 1

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
Run Code Online (Sandbox Code Playgroud)

也许这是我以前不知道的事情,但是 Django 是否要求您在使用子类模型的所有形式中提供指向超类的指针?这让我很惊讶。

我想知道为什么需要这个指针字段,所以我在这里提出了一个问题来解决这个问题:为什么我的 django 表单集需要指针字段引用?