【问题标题】:How can I build multiple submit buttons django form?如何构建多个提交按钮 django 表单?
【发布时间】:2010-10-26 08:39:55
【问题描述】:

我有一个表单,其中包含一个电子邮件输入和两个提交按钮,用于订阅和取消订阅时事通讯:

<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 字典中。 否则我可以获取按钮的值吗?

【问题讨论】:

    标签: python django button django-forms submit


    【解决方案1】:

    例如:

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

    【讨论】:

    • 在 clean_xxx 验证方法中是否提供请求?
    • 这个应该用什么方法?
    • @JonMcClung Inside def post(self, request, *args, **kwargs).
    【解决方案2】:

    您可以在clean_email 方法中使用self.data 在验证之前访问POST 数据。它应该包含一个名为 newsletter_subnewsletter_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
    

    【讨论】:

    • 你能举一个带注释的例子吗?真的很有帮助
    • 我认为clean 并不是真正适合进行模型级逻辑的地方。它专门用于清理表单并查找跨越多个输入的任何ValidationErrors。斯文的答案比较正确,但仍不一定是最佳答案
    • 安全风险!在验证表单之前使用表单数据在数据库中进行更改是危险的。
    • 您可能希望根据按下的按钮运行不同类型的验证。在这种情况下,没有“安全”影响。
    【解决方案3】:

    你也可以这样做,

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

    【讨论】:

    • form1.as_p 什么时候用这个??在视图中,在检查表单的有效性时,我希望我可以这样做... form1.is_valid() 然后执行此操作,form2.is_valid() 执行此操作..
    【解决方案4】:

    同一个视图的一个网址! 就这样!

    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>
    

    【讨论】:

    • 我应该如何引用其他 html 文件中的特定视图 href = "{% url 'appname:viewname' %}"
    • views.py 中的表单应该提供什么
    • 为什么要在post函数中测试方法是否为POST?仅当 http 方法为 POST 时,基于类的视图才会调用 post 函数。
    • 我似乎不记得为什么看到这是 4 年前的事了。但是,我似乎记得这是必要的,因为循环操作方法是提交一个表单而不是另一个表单。不过不完全确定。
    【解决方案5】:

    现在这是一个老问题了,不过我遇到了同样的问题并找到了一个适合我的解决方案:我写了 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
    

    【讨论】:

    • 您将在何处以及如何使用 MultiRedirectMixin?请举例说明。
    【解决方案6】:

    我知道这已经过时了,但至少可以说,有些答案很简短,而且它们没有解决表单不是 django 表单的常见情况。

    此解决方案的灵感来自 this blog post。它依赖于使用从 django.views.generic.edit.FormMixin 派生的视图类,例如CreateView、UpdateView 或 DeleteView。这些提供了 get_success_url 方法,该方法在 request

    中公开按钮名称

    html

    <html>
        <body>
            <form method="post">
                <div>
                    <label> <input type="radio" name="select-type" value="A">Type A</label>
                </div>
                <div>
                    <label> <input type="radio" name="select-type" value="B">Type B</label>
                </div>
                <div>
                    <input type="submit" value="Use selected">
                </div>
                <div>
                    <input type="submit" name="no-selection" value="None of the above">
                </div>
            </form>
        </body>
    </html>
    

    views.py

    from django.views.generic import UpdateView
    
    class GetType(UpdateView):
        def get(self, request):
            return render(request, 'get_type.html', {})
    
        def post(self, request):
            button = self.get_success_url()
            print(button)
    
        def get_success_url(self):
            if 'no-selection' in self.request.POST:
                return 'none selected'
            return ''
    

    【讨论】:

      猜你喜欢
      • 2015-10-04
      • 2013-02-13
      • 2017-05-03
      • 2023-03-10
      • 2021-08-11
      • 2019-03-19
      • 1970-01-01
      • 2016-09-24
      • 2012-06-12
      相关资源
      最近更新 更多