web-dev-qa-db-fra.com

Django modifier le formulaire en fonction du formulaire d'ajout?

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

  1. Où dois-je définir 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.
  2. Si le formulaire est réellement est invalide, le champ que j'ai ajouté dynamiquement dans la fonction d'édition n'est pas conservé.

Alors, comment dois-je gérer cela?

44
mpen

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',)
100
Daniel Naab

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

2
Anurag Uniyal