45

[これをDjango ユーザーに投稿しました| Google グループも。]

inline formset docsの例を使用して、特定のモデルに属するオブジェクトを編集できます (modelforms を使用)。私はインライン フォームセットを使用して新しいオブジェクトを作成するために同じパターンに従おうとしまし たが、この目的のための作業ビューを引き出すのに十分な頭をクリアすることができませんでした。

上記のリンクと同じ例を使用して、関連する「Book」オブジェクトとともに「Author」モデルの新しいインスタンスを作成するにはどうすればよいでしょうか?

4

3 に答える 3

38

まず、Author モデル フォームを作成します。

author_form = AuthorModelForm()

次に、ダミーの作成者オブジェクトを作成します。

author = Author()

次に、次のようにダミーの作成者を使用してインライン フォームセットを作成します。

formset = BookFormSet(instance=author)  #since author is empty, this formset will just be empty forms

それをテンプレートに送信します。データがビューに返されたら、Author を作成します。

author = AuthorModelForm(request.POST)
created_author = author.save()  # in practice make sure it's valid first

新しく作成された作成者でインライン フォームセットをフックし、保存します。

formset = BookFormSet(request.POST, instance=created_author)
formset.save()   #again, make sure it's valid first

編集:

新しいフォームにチェックボックスを持たないようにするには、これをテンプレートにします:

{% for form in formset.forms %}
    <table>
    {% for field in form %}
        <tr><th>{{field.label_tag}}</th><td>{{field}}{{field.errors}}</td></tr>
    {% endfor %}

    {% if form.pk %} {# empty forms do not have a pk #}
         <tr><th>Delete?</th><td>{{field.DELETE}}</td></tr>
    {% endif %}
    </table>
{% endfor %}
于 2009-07-11T06:27:26.103 に答える
37

実際、nbv4 のソリューションを少し調整することを提案したいと思います。

if-else ステートメントの外で空の created_author を作成しないため、author_form が有効でない (したがって、created_author がインスタンス化されていない) 場合の実行時エラーを回避するために、フォームセットを author_form.is_valid() 内にネストする必要があると仮定します。

それ以外の:

if request.method == 'POST':
    author_form = AuthorModelForm(request.POST)
    if author_form.is_valid():
        created_author = author_form.save()
        formset = BookFormSet(request.POST, instance=created_author)
        if formset.is_valid():
            formset.save()
            return HttpResponseRedirect(...)
else:
    ...

以下をせよ:

if request.method == 'POST':
    author_form = AuthorModelForm(request.POST)
    if author_form.is_valid():
        created_author = author_form.save(commit=False)
        formset = BookFormSet(request.POST, instance=created_author)
        if formset.is_valid():
            created_author.save()
            formset.save()
            return HttpResponseRedirect(...)
else:
    ...

このバージョンでは、book_formset が検証される機会が得られるまで、created_author のコミットが回避されます。修正すべき使用例は、誰かが有効な AuthorForm に無効な BookFormSet を入力し、再送信を続けて、書籍が関連付けられていない複数の Author レコードを作成することです。これは、私のプロジェクト トラッカー アプリで機能するようです (「Author」を「Project」に、「Book」を「Role」に置き換えます)。

于 2011-02-02T15:47:18.873 に答える
10

models.py (連絡先)

class Contact(models.Model)
    first = models.CharField(max_length=30)
    middle = models.CharField('M.I.',max_length=30, blank=True)
    last = models.CharField(max_length=30)
    sort_order = models.PositiveIntegerField(default=99)

models.py (リンク)

class Link(models.Model):
    contact = models.ForeignKey(Contact)
    link = models.URLField()
    description = models.CharField(max_length=30)
    access_date = models.DateField(blank=True,null=True)

フォーム.py

from django.forms import ModelForm
from contacts.models import Contact

class ContactAjaxForm(ModelForm):
    class Meta:
        model=Contact

ビュー.py

def edit(request,object_id=False):
    LinkFormSet = inlineformset_factory(Contact, Link, extra=1)
    if object_id:
        contact=Contact.objects.get(pk=object_id)
    else:
        contact=Contact()
    if request.method == 'POST':
        f=forms.ContactAjaxForm(request.POST, request.FILES, instance=contact)
        fs = LinkFormSet(request.POST,instance=contact)
        if fs.is_valid() and f.is_valid():
            f.save()
            fs.save()
            return HttpResponse('success')
    else:
        f  = forms.ContactAjaxForm(instance=contact)
        fs = LinkFormSet(instance=contact)
    return render_to_response(
        'contacts/edit.html', 
        {'fs': fs, 'f': f, 'contact': contact}
    )

これは本の例に基づいているのではなく、私のサイトのいくつかのコードから編集されています。私はそれをテストしていないので、いくつかのバグがあるかもしれませんが、全体的にはしっかりしているはずです. Contact の空のインスタンスを使用することは推奨される方法ではありませんが、ロジックを少し節約でき、機能します。

編集: リンクモデルを追加し、混乱を招く汎用外部キーの代わりに通常の外部キーに切り替えました

于 2009-07-11T06:28:22.607 に答える