2014-01-21 27 views
8

我最近通过继承FormView了解了Django表单,其中所需表单被分配到FormView.form_class属性。表单验证后,将调用form_valid()方法(针对该表单)。例如:Django:使用FormView时可能有多种形式?

from accounts.forms import SignUpForm, UpdateAccountForm, UpdateBillingForm 

class SignUpView(FormView): 
    form_class = SignUpForm 

    def form_valid(self, form): 
    # code when form validates... 

不过,我现在有一个情况下,我需要一个页面(在一时刻对用户可见的只有一种形式)的三个独特的形式。所以,我想在同一个视图中处理它们。

是否可以使用FormView的多表单页面?我不确定如何处理它,无论是将多种形式传递给视图(例如其他UpdateAccountForm和UpdateBillingForm),还是区分哪一个被提交/验证?什么是最好的方法?

+0

看起来像它不可能与FormView控件(?)。每个这些[答案](http://stackoverflow.com/questions/1395807/proper-way-to-handle-multiple-forms-on-one-page-in-django),应该使用一个通用的视图,并添加前缀(?) – pete

+1

我刚刚写了一个工具来完成这件事,截至目前只有部分记录,但类MultFormView只是一些代码来处理你正在尝试做什么https://github.com/dm03514/Django的CBV的工具包 – dm03514

回答

0

你可以编写一个模拟Form API(至少是有用的部分)的普通python类,并包装你的三种形式。检测提交的表单只是在每个表单中添加一个带有表单标识符的隐藏输入(提示:为表单使用前缀并使用相同的前缀作为标识符)。

另一种解决方案是使用简单的基于函数的视图,但即使在那里,我仍然会使用相同的“表单包装器”模式。

10

那么,这里最值得称道的是使用通用视图。

1)我在页面上为每个单独的表单添加了一个隐藏的输入字段(名为'action')。例如,这是用于更新用户的信息,这是在用户窗体拉动形式:

<form action='/account/' method='post'>{% csrf_token %} 
    <input type='hidden' name='action' value='edit_user'> 
    {{ user_form.as_p }} 
    <input type='submit' value='Update'> 
</form> 

2)在我的视图逻辑,I可以通过施加一个前缀区分形式(每其他SO柱和Django的docs) 。然后,根据传入的“操作”,我只将适用的表单绑定到POST请求(所以验证不适用于所有这些表单)。就我而言,我在forms.py,用户窗体和BillingForm定义两种形式:

from django.views.generic.edit import View 
from django.shortcuts import render 
from django.http import HttpResponse 

from accounts.forms import UserForm, BillingForm 

class AccountView(View): 

    def get(self, request): 
     # code for GET request... 

    def post(self, request): 
     #instantiate all unique forms (using prefix) as unbound 
     user_form = UserForm(prefix='user_form') 
     billing_form = BillingForm(prefix='billing_form') 

     # determine which form is submitting (based on hidden input called 'action') 
     action = self.request.POST['action'] 

     # bind to POST and process the correct form 
     if (action == 'edit_user'): 
      user_form = UserForm(request.POST, prefix='user_form') 
      if user_form.is_valid(): 
       # user form validated, code away.. 

     elif (action == 'edit_billing'): 
      billing_form = BillingForm(request.POST, prefix='billing_form') 
      if billing_form.is_valid(): 
       # billing form validated, code away.. 

     # prep context 
     context = { 
      'user_form': user_form, 
      'billing_form': billing_form, 
     } 
     return render(request, 'accounts/account.html', context) 

似乎运作良好,希望这是正确的做法