Django:使用FormView时可能有多种形式?

pet*_*ete 11 python django

我最近通过子类化学习了Django表单FormView,其中所需的表单被分配给FormView.form_class属性.当表单验证时,将form_valid()调用该方法(对于该表单).例如:

from accounts.forms import SignUpForm, UpdateAccountForm, UpdateBillingForm

class SignUpView(FormView):
    form_class = SignUpForm

    def form_valid(self, form):
    # code when form validates...
Run Code Online (Sandbox Code Playgroud)

但是,我现在有一种情况,我需要在一个页面上有三个独特的表单(一次只有一个表单对用户可见).所以,我想在同一个视图中处理它们.

使用FormView可以实现多表单页面吗?我不知道如何处理它,无论是将多个表单传递给View(例如另一个UpdateAccountForm和UpdateBillingForm),还是区分哪个表单已提交/验证?什么是最好的方式?

pet*_*ete 15

嗯,这里有什么价值,最终对我有用,使用通用视图.

1)我在页面上的每个单独的表单中添加了一个隐藏的输入字段(名为"action").例如,这是用于更新用户信息的表单,其中包含UserForm:

<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>
Run Code Online (Sandbox Code Playgroud)

2)在我的View逻辑中,我可以通过应用前缀(每个其他SO帖子和Django 文档)来区分表单.然后,根据传入的"操作",我只将适用的表单绑定到POST请求(因此不会对所有这些请求应用验证).在我的例子中,我在forms.py,UserForm和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) 
Run Code Online (Sandbox Code Playgroud)

似乎运作良好,希望这是正确的方法(?)


bru*_*ers 1

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

另一个解决方案是使用简单的基于函数的视图,但即使如此,就我而言,我仍然会使用相同的“表单包装器”模式。