J'ai créé un joli formulaire, et une grande fonction "ajouter" compliquée pour le gérer. Ça commence comme ça ...
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 ...
Maintenant, je ne veux pas vraiment dupliquer toutes ces fonctionnalités dans la méthode edit()
, donc j'ai pensé que edit
pourrait utiliser exactement le même modèle, et peut-être simplement ajouter un id
au formulaire afin que la fonction add
sache ce qu'elle modifie. Mais il y a quelques problèmes avec ça
article.id
Dans la fonction add
? Il faudrait que ce soit après form.save
Parce que c'est là que l'article est créé, mais il n'atteindrait même jamais cela, car le formulaire n'est pas valide en raison de contraintes uniques (à moins que l'utilisateur n'ait tout modifié). Je peux simplement supprimer la vérification is_valid
, Mais form.save
Échoue à la place.Alors, comment dois-je gérer cela?
Si vous étendez votre formulaire à partir d'un ModelForm, utilisez l'argument de mot clé instance
. Ici, nous transmettons un instance
existant ou un nouveau, selon que nous modifions ou ajoutons un article existant. Dans les deux cas, le champ author
est défini sur l'instance, donc commit=False
n'est pas requis. Notez également que je suppose que seul l'auteur peut éditer ses propres articles, d'où la réponse 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
})
Et dans votre urls.py
:
(r'^article/new/$', views.edit, {}, 'article_new'),
(r'^article/edit/(?P<id>\d+)/$', views.edit, {}, 'article_edit'),
La même vue edit
est utilisée pour les ajouts et les modifications, mais seul le modèle d'url de modification transmet un identifiant à la vue. Pour que cela fonctionne bien avec votre formulaire, vous devrez omettre le champ author
du formulaire:
class ArticleForm(forms.ModelForm):
class Meta:
model = Article
exclude = ('author',)
Vous pouvez avoir un champ d'ID masqué dans le formulaire et pour le formulaire d'édition, il sera transmis avec le formulaire pour ajouter un formulaire, vous pouvez le définir dans REQ.POST, par ex.
formData = req.POST.copy()
formData['id'] = getNewID()
et passez ce formData pour former