Niceフォームを作成し、それを処理するための大きく複雑な「追加」機能を作成しました。このように始まります...
_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
_はどこに設定しますか?それは_form.save
_の後でなければなりません。それは記事が作成される場所だからです。しかし、フォームが一意の制約のために無効であるため(ユーザーがすべてを編集しない限り)それに到達することさえありません。 _is_valid
_チェックを削除するだけですが、_form.save
_は代わりに失敗します。それで、どうすればこれに対処できますか?
ModelFormからフォームを拡張する場合は、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',)
フォームに非表示のIDフィールドを設定できます。編集フォームの場合、追加フォームのフォームと共に渡され、req.POSTで設定できます。
formData = req.POST.copy()
formData['id'] = getNewID()
そしてそのformDataをformに渡します