Wie kann ich mehrere Django-Formulare für Senden-Schaltflächen erstellen?

155

Ich habe ein Formular mit einer Eingabe für E-Mail und zwei Senden-Schaltflächen zum Abonnieren und Abbestellen des Newsletters:

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

Ich habe auch Klassenform:

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

Ich muss meine eigene clean_email-Methode schreiben und wissen, über welche Schaltfläche das Formular gesendet wurde. Der Wert der Senden-Schaltflächen befindet sich jedoch nicht im self.cleaned_dataWörterbuch. Könnte ich sonst Werte von Schaltflächen erhalten?

veena
quelle

Antworten:

96

Mit self.datadieser clean_emailMethode können Sie vor der Validierung auf die POST-Daten zugreifen. Es sollte eine Taste enthalten, die aufgerufen wird newsletter_suboder newsletter_unsubje nachdem, welche Taste gedrückt wurde.

# 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
Ayman Hourieh
quelle
4
Können Sie ein kommentiertes Beispiel geben? es würde wirklich helfen
Jharwood
9
Ich denke nicht, dass dies cleannicht der richtige Ort ist, um Logik auf Modellebene zu erstellen. Es dient speziell zum Bereinigen eines Formulars und zum Auffinden von Formularen ValidationError, die mehrere Eingaben umfassen. Svens Antwort ist eher in die richtige Richtung, aber immer noch nicht unbedingt die beste Antwort
Patrick
8
Sicherheitsrisiko! Die Verwendung von Formulardaten, um Änderungen in der Datenbank vorzunehmen, bevor das Formular validiert wurde, ist gefährlich.
Quant Metropolis
1
Je nachdem, welche Taste gedrückt wurde, möchten Sie möglicherweise verschiedene Validierungsarten ausführen. In diesem Fall gibt es keine Auswirkungen auf die "Sicherheit".
sureshvv
230

Z.B:

if 'newsletter_sub' in request.POST:
    # do subscribe
elif 'newsletter_unsub' in request.POST:
    # do unsubscribe
Damon Abdiel
quelle
1
Ist eine Anforderung in den Validierungsmethoden clean_xxx verfügbar?
sureshvv
In welche Methode soll das gehen?
Jon McClung
1
@ JonMcClung Inside def post(self, request, *args, **kwargs).
A. Kali
23

Sie können auch so tun,

 <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>

CODE

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

quelle
form1.as_p wann soll man das benutzen ?? In den Ansichten, während ich die Gültigkeit des Formulars überprüfe, wünschte ich, ich könnte ... form1.is_valid () dann tun, form2.is_valid () tun dies ..
Tilaprimera
5

Es ist jetzt eine alte Frage, trotzdem hatte ich das gleiche Problem und fand eine Lösung, die für mich funktioniert: Ich habe MultiRedirectMixin geschrieben.

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
Sven
quelle
Wo und wie genau werden Sie MultiRedirectMixin verwenden? Bitte erläutern Sie dies anhand eines Beispiels.
Saurav Kumar
4

eine URL zur gleichen Ansicht! wie so!

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>
chrisroker0
quelle