2012-12-02 33 views
13

フォームセットを投稿すると、MultiValueDictKeyErrorが返されます。具体的に:Formset POSTでDjango 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はPOSTデータの重要documents-0-attachment_ptrを探しているということです。これは混乱します。ドキュメントは添付ファイルのサブクラスです。他の投稿データはすべて期待通りです。なぜ私のフォームセットにポインタデータが必要なのですか?

ここではフォームセットで使用されてフォーム:

""" 
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ポスト

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 

そして、ここでは、ドキュメントのモデルでありますformsetは正常に動作します。このエラーが発生したときに、フォームセットに初期フォームがあるときは、更新ポストにのみあります。また、フォームセットからフォームを削除しようとすると発生します。

また、formsetはdjango crispyフォームを使用する一般的なインラインフォームセットです。

更新

使用テンプレートコードの要求がありました。ここでは単純化されたバージョンは次のとおりです。

{% 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> 
+0

をNoDirectoryClearableFileInputは何ですか?おそらく、テンプレートHTMLとJavaScriptコードを投稿する必要があります。 – danihp

+0

NoDirectoryClearableFileInputは、関連ファイルの絶対パスではなく、ファイル名のみを表示するClearableFileInputウィジェットのサブクラスです。 – Erik

+0

JavaScriptに関連するものはありません。 – Erik

答えて

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 

は、多分それは私が前に知らなかったものですが、Djangoは、サブクラス化モデルを使用するすべての形態のスーパークラスへのポインタを提供する必要がありませんか?これは私を驚かせる。

私はこのポインタフィールドが必要な理由を知りたいので、ここでそれに対処するための質問を開きました:Why does my django formset need a pointer field reference?

43

これはOPでのケースではありませんが、テンプレートに隠れフィールドの一部がない場合は、MultiValueDictKeyErrorが発生します。 {{form}}の代わりに、テンプレートに1つずつフィールドが表示されるときに、{{form.field1}}{{form.field2}}というフィールドが必要な場合は、非表示にする必要があります。戻ってそれらを含めるように

は(フォームセット内の各フォーム/フォームの)線に沿って何かを実行します。

{% for hidden in form.hidden_fields %} 
    {{ hidden }} 
{% endfor %} 

または

{% for form in formset %}  
    {% for hidden in form.hidden_fields %} 
     {{ hidden }} 
    {% endfor %}  
{% endfor %} 
4

私はこのような

{% for hidden in form.hidden_fields %} 
    {{ hidden }} 
{% endfor %} 

も使用します1

<div role="tabpanel" class="tab-pane active" id="email"> 
       {% csrf_token %} 
       {{ eformset.management_form}} 
        <div class="panel panel-default"> 
         <div class="panel-body"> 
          <div id="addemail" class="btn btn-success"> 
           <span class="glyphicon glyphicon-plus" > 
           </span> 
          </div> 
          <p><br></p> 
          {% for f in eformset %} 
           {% for hidden in f.hidden_fields %} 
            {{ hidden }} 
           {% endfor %} 
           <div class="item_email_set"> 
            <table class="table table-condensed table-bordered"> 
            <tr> 
             {% for field in f.visible_fields %} <!----> 
              <td> 
               {{ field.label }} 
              </td> 
             {% endfor %} 

             <td> 
             </td> 
            </tr> 
            <tr> 
             {% for field in f.visible_fields %} 
              <td> 
               {{field.errors.as_ul}} 
               {{field}} 
              </td> 
             {% endfor %}  
             <td class="btncolumn">  
              <p style=""> 
               <a class="delete_email_set" href="#"> 
                <div class="btn btn-danger"> 
                 <span class="glyphicon glyphicon-remove" > 
                 </span> 
                </div> 
               </a> 
              </p> 
             </td> 
            </tr> 

           </table> 
          </div> 
         {% endfor %} 
        </div> 
       </div> 
      </div> 

と私はMultiValueDictKeyErrorを解決しました

0

これはOPの回答ではありませんが、私は同じエラーがあります。私は間違って私のテンプレートから{{ subform.id }}を削除しました。視覚的に見ることができず、古いコードを整理していました。 あなたのHTMLでは、あなたのようなものでしょう:

<input name="note_set-0-id" value="34632" id="id_note_set-0-id" type="hidden"> 
関連する問題