3

情報:

次の場所にある例で最もよく説明されているように、ネストされたフォームを作成したいと思います。

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 

私が得ているエラーメッセージは次のとおりです。

ValidationError at "urlName":
[u'ManagementForm data is missing or has been tampered with']

私はより深く掘り下げましたが、この失敗は site-packages/django/forms/formsets.py の行で発生しているようです

一部のis_valid()管理フォームの必須データ (form-TOTAL_FORMS、form-INITIAL_FORMS、および form-MAX_NUM_FORMS) が無効であるため、チェックに失敗しています。以下は、self.errors の実際の出力です。

{u'TOTAL_FORMS': [u'This field is required.'], u'INITIAL_FORMS': [u'This field is required.']}

コード:

edit_building.html:

{{ building.management_form }}

{% building in building.forms %}

 {{ building }}

 {% if building.nested %}   
   {% for formset in building.nested %}   
     {{ formset.as_table }}   
   {% endfor %}   
 {% endif %}

{% endfor %}

ビュー.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)

フォーム.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)

ノート:

質問:

POST データがなく、フォームがデータベースからのみ生成されている場合、この失敗を解決するには、'form-TOTAL_FORMS' && 'form-INITIAL_FORMS' データを正しく入力するにはどうすればよいですか?

4

1 に答える 1

5

アップデート:

あなたが提供した例を調べた後、メソッドforms.pyの最後に次のようなスニペットがあります。add_fields()

# store the formset in the .nested property
form.nested = [
    TenantFormset(data = self.data,
                  instance = instance,
                  prefix = 'TENANTS_%s' % pk_value)
]

引数は最初は空で、内部的に Django がフォームが次のような条件によってバインドdataされているかどうかを判断するため、問題が発生しています。

self.is_bound = data is not None

# Example
>>> my_data = {}
>>> my_data is not None
True

また、ご覧のとおり、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)
]

ビューとフォームのコード、およびフォームのテンプレート コードを投稿していただけますか?

私の推測では、テンプレートで「management_form」を使用していない (「form-TOTAL_FORMS」フィールドと「form-INITIAL_FORMS」フィールドが追加されています)。

<form method="post">
    {{ formset.management_form }}
    <table>
        {% for form in formset %}
        {{ form }}
        {% endfor %}
    </table>
</form>
于 2013-07-08T01:42:21.253 に答える