Come posso creare più moduli django pulsanti di invio?


156

Ho un modulo con un input per e-mail e due pulsanti di invio per iscriversi e annullare l'iscrizione alla newsletter:

<form action="" method="post">
{{ form_newsletter }}
<input type="submit" name="newsletter_sub" value="Subscribe" />
<input type="submit" name="newsletter_unsub" value="Unsubscribe" />
</form>

Ho anche un modulo di classe:

class NewsletterForm(forms.ModelForm):
    class Meta:
        model = Newsletter
        fields = ('email',)

Devo scrivere il mio metodo clean_email e devo sapere con quale pulsante è stato inviato il modulo. Ma il valore dei pulsanti di invio non è nel self.cleaned_datadizionario. In caso contrario, potrei ottenere i valori dei pulsanti?

Risposte:


97

È possibile utilizzare self.datanel clean_emailmetodo per accedere ai dati POST prima della convalida. Dovrebbe contenere un tasto chiamato newsletter_subo in newsletter_unsubbase al pulsante premuto.

# in the context of a django.forms form

def clean(self):
    if 'newsletter_sub' in self.data:
        # do subscribe
    elif 'newsletter_unsub' in self.data:
        # do unsubscribe

4
puoi fare un esempio annotato? sarebbe davvero d'aiuto
Jharwood,

9
Non penso che cleannon sia davvero il tipo giusto di posto dove fare la logica a livello di modello. È specifico per la pulizia di un modulo e la ricerca di qualsiasi ValidationErrors che si estende su più input. La risposta di Sven è più nella giusta direzione, ma non è necessariamente la migliore risposta
Patrick

8
Rischio per la sicurezza! L'uso dei dati del modulo per apportare modifiche al database prima della convalida del modulo è pericoloso.
Quant Metropolis

1
È possibile che si desideri eseguire diversi tipi di convalida a seconda del pulsante premuto. In tal caso, non vi è alcun impatto "Sicurezza".
sureshvv,

230

Per esempio:

if 'newsletter_sub' in request.POST:
    # do subscribe
elif 'newsletter_unsub' in request.POST:
    # do unsubscribe

1
La richiesta è disponibile nei metodi di convalida clean_xxx?
sureshvv,

In quale metodo dovrebbe andare?
Jon McClung,

1
@JonMcClung Inside def post(self, request, *args, **kwargs).
A. Kali,

23

Puoi anche fare così,

 <form method='POST'>
    {{form1.as_p}}
    <button type="submit" name="btnform1">Save Changes</button>
    </form>
    <form method='POST'>
    {{form2.as_p}}
    <button type="submit" name="btnform2">Save Changes</button>
    </form>

CODICE

if request.method=='POST' and 'btnform1' in request.POST:
    do something...
if request.method=='POST' and 'btnform2' in request.POST:
    do something...

form1.as_p quando usarlo ?? il punto di vista, mentre si controlla la validità della forma, vorrei poter fare ... form1.is_valid () poi fare questo, form2.is_valid () fare questo ..
tilaprimera

5

È una vecchia domanda ora, tuttavia ho avuto lo stesso problema e ho trovato una soluzione che funziona per me: ho scritto MultiRedirectMixin.

from django.http import HttpResponseRedirect

class MultiRedirectMixin(object):
    """
    A mixin that supports submit-specific success redirection.
     Either specify one success_url, or provide dict with names of 
     submit actions given in template as keys
     Example: 
       In template:
         <input type="submit" name="create_new" value="Create"/>
         <input type="submit" name="delete" value="Delete"/>
       View:
         MyMultiSubmitView(MultiRedirectMixin, forms.FormView):
             success_urls = {"create_new": reverse_lazy('create'),
                               "delete": reverse_lazy('delete')}
    """
    success_urls = {}  

    def form_valid(self, form):
        """ Form is valid: Pick the url and redirect.
        """

        for name in self.success_urls:
            if name in form.data:
                self.success_url = self.success_urls[name]
                break

        return HttpResponseRedirect(self.get_success_url())

    def get_success_url(self):
        """
        Returns the supplied success URL.
        """
        if self.success_url:
            # Forcing possible reverse_lazy evaluation
            url = force_text(self.success_url)
        else:
            raise ImproperlyConfigured(
                _("No URL to redirect to. Provide a success_url."))
        return url

Dove e come utilizzerai esattamente MultiRedirectMixin? Si prega di elaborare con un esempio.
Saurav Kumar,

4

un URL per la stessa vista! così!

urls.py

url(r'^$', views.landing.as_view(), name = 'landing'),

views.py

class landing(View):
        template_name = '/home.html'
        form_class1 = forms.pynamehere1
        form_class2 = forms.pynamehere2
            def get(self, request):
                form1 = self.form_class1(None)
                form2 = self.form_class2(None)
                return render(request, self.template_name, { 'register':form1, 'login':form2,})

             def post(self, request):
                 if request.method=='POST' and 'htmlsubmitbutton1' in request.POST:
                        ## do what ever you want to do for first function ####
                 if request.method=='POST' and 'htmlsubmitbutton2' in request.POST:
                         ## do what ever you want to do for second function ####
                        ## return def post###  
                 return render(request, self.template_name, {'form':form,})
/home.html
    <!-- #### form 1 #### -->
    <form action="" method="POST" >
      {% csrf_token %}
      {{ register.as_p }}
    <button type="submit" name="htmlsubmitbutton1">Login</button>
    </form>
    <!--#### form 2 #### -->
    <form action="" method="POST" >
      {% csrf_token %}
      {{ login.as_p }}
    <button type="submit" name="htmlsubmitbutton2">Login</button>
    </form>
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.