2009-12-06 25 views
36

私は素敵なフォームとそれを扱うための大きな複雑な「追加」機能を作りました。それはこのように始まり...Djangoはフォームを追加してフォームを編集しますか?

def add(req): 
    if req.method == 'POST': 
     form = ArticleForm(req.POST) 
     if form.is_valid(): 
      article = form.save(commit=False) 
      article.author = req.user 
      # more processing ... 

は今、私は本当にedit()方法ですべてが機能を複製したくないので、私はeditがまったく同じテンプレートを使用し、多分ちょうどにidフィールドを追加することができます考え出しそのフォームはaddの機能で編集内容を知っていました。しかし、私はadd FUNCにarticle.idを設定します。この

  1. と夫婦の問題がありますか?それはform.saveの後になければなりません。これは、記事が作成される場所ですが、ユーザーがすべてを編集しない限り、フォームが一意的な制約のために無効であるために到達することさえありません。私はちょうどis_validチェックを削除することができますが、form.saveは代わりに失敗します。
  2. 実際にフォームが無効の場合は、編集機能で動的に追加されたフィールドIが無効になります。

どうすればこの問題に対処できますか?

答えて

88

を形成instanceキーワード引数を使用することを渡します。ここでは、既存の記事を編集するか追加するかによって、既存のinstanceまたは新しいものが渡されます。どちらの場合もauthorフィールドがインスタンスに設定されているため、commit=Falseは不要です。また、著者だけが自分の記事を編集できると仮定しているので、HttpResponseForbiddenレスポンスを参照してください。

from django.http import HttpResponseForbidden 
from django.shortcuts import get_object_or_404, redirect, render, reverse 


@login_required 
def edit(request, id=None, template_name='article_edit_template.html'): 
    if id: 
     article = get_object_or_404(Article, pk=id) 
     if article.author != request.user: 
      return HttpResponseForbidden() 
    else: 
     article = Article(author=request.user) 

    form = ArticleForm(request.POST or None, instance=article) 
    if request.POST and form.is_valid(): 
     form.save() 

     # Save was successful, so redirect to another page 
     redirect_url = reverse(article_save_success) 
     return redirect(redirect_url) 

    return render(request, template_name, { 
     'form': form 
    }) 

そして、あなたのurls.py中:

(r'^article/new/$', views.edit, {}, 'article_new'), 
(r'^article/edit/(?P<id>\d+)/$', views.edit, {}, 'article_edit'), 

同じeditビューは両方のために使用されているが追加され、編集が、唯一の編集URLパターンがビューにIDを渡します。あなたのフォームでうまくいくようにするには、フォームからauthorフィールドを省略する必要があります:

class ArticleForm(forms.ModelForm): 
    class Meta: 
     model = Article 
     exclude = ('author',) 
+0

はい、それは 'ModelForm'です。私は他の理由で 'commit = False'を必要としました。記事は、たくさんのものから構成されています(いくつかのm2m関係を含む)。私は*インスタンス*で作業したいと思っていません。私はこれを試してみましょう。 – mpen

+1

その場合、ビューの代わりにフォームにm2m relations(et al)の保存/検証を入れることをお勧めします。saveメソッドをオーバーライドするか、おそらくフォームセットを調べます。私はそれがあなたと一緒に働いているのコンテキストに依存していると思います... –

+5

素晴らしいと徹底的な例!ありがとう!私はこの質問に対するちょうど解決策以上のことを学びました。 – hobbes3

1

フォームにIDフィールドを隠しておくことができます。編集フォームの場合、req.POSTに設定できる追加フォームのフォームと一緒に渡されます。

formData = req.POST.copy() 
formData['id'] = getNewID() 

とFORMDATAあなたはのModelFormからフォームを拡張している場合は、

関連する問題