Как я могу создать форму django с несколькими кнопками отправки?

У меня есть форма с одним входом для электронной почты и двумя кнопками отправки для подписки и отказа от подписки на информационный бюллетень:

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

У меня также есть форма класса:

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

Я должен написать свой собственный метод clean_email, и мне нужно знать, с помощью какой кнопки была отправлена ​​форма. Но значение кнопок отправки отсутствует в self.cleaned_data словаре. Могу ли я получить значения кнопок иначе?


person veena    schedule 14.05.2009    source источник


Ответы (5)


Вы можете использовать self.data в методе clean_email для доступа к данным POST перед проверкой. Он должен содержать клавишу с именем newsletter_sub или newsletter_unsub в зависимости от того, какая кнопка была нажата.

# 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
person Ayman Hourieh    schedule 14.05.2009
comment
можешь привести аннотированный пример? это действительно поможет - person Jharwood; 25.10.2012
comment
Я не думаю, что clean на самом деле не подходящее место для логики на уровне модели. Это специально для очистки формы и поиска любых ValidationError, которые охватывают несколько входов. Ответ Свена более верный, но все же не обязательно лучший. - person Patrick; 06.08.2014
comment
Риск безопасности! Использование данных формы для внесения изменений в базу данных до проверки формы опасно. - person Quant Metropolis; 14.03.2016
comment
Возможно, вы захотите запустить разные типы проверки в зависимости от того, какая кнопка была нажата. В этом случае влияние на безопасность отсутствует. - person sureshvv; 25.09.2016

Вы также можете сделать это,

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

КОД

if request.method=='POST' and 'btnform1' in request.POST:
    do something...
if request.method=='POST' and 'btnform2' in request.POST:
    do something...
person Community    schedule 03.06.2013
comment
form1.as_p когда это использовать ?? в представлениях, проверяя правильность формы, я хотел бы сделать ... form1.is_valid (), затем сделайте это, form2.is_valid () сделайте это .. - person hlkstuv_23900; 29.10.2014

один URL к тому же представлению! вот так!

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>
person chrisroker0    schedule 29.03.2017
comment
как мне ссылаться на конкретное представление из других html файлов href = {% url 'appname: viewname'%} - person uma_8331; 01.03.2021
comment
что я должен дать для формы в views.py - person uma_8331; 02.03.2021
comment
Почему вы проверяете, является ли метод POST в функции post? Представления на основе классов вызывают функцию post только в том случае, если метод http - POST. - person Braiam; 13.03.2021
comment
Кажется, я не могу вспомнить, почему это было 4 года назад. Тем не менее, я, кажется, вспомнил, что это было необходимо из-за метода кругового действия, когда одна форма отправлялась, а другая не передавалась. Хотя не совсем уверен. - person chrisroker0; 14.03.2021

Это старый вопрос, тем не менее, у меня была такая же проблема, и я нашел решение, которое работает для меня: я написал 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
person Sven    schedule 06.05.2014
comment
Где и как именно вы будете использовать MultiRedirectMixin? Уточните пример. - person Saurav Kumar; 24.02.2017

person    schedule
comment
Доступен ли запрос внутри методов проверки clean_xxx? - person sureshvv; 25.09.2016
comment
Каким образом это должно происходить? - person Jon McClung; 20.11.2019
comment
@JonMcClung Внутри def post(self, request, *args, **kwargs). - person A. Kali; 04.12.2019