Django: При использовании FormView возможны несколько форм?

Недавно я изучил формы 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...

Однако теперь у меня есть ситуация, когда мне нужно три уникальные формы на одной странице (только одна форма, видимая пользователю за раз). Поэтому я хотел бы обрабатывать их все в одном представлении.

Возможно ли использование многоформатных страниц с помощью FormView? Я не уверен, как справиться с этим, как с точки зрения передачи нескольких форм в представление (например, другой UpdateAccountForm и UpdateBillingForm), так и для выделения того, какой из них был отправлен/подтвержден? Каким будет лучший способ?

Ответ 1

Хорошо, для чего это стоит, что в конечном итоге сработало для меня, используя общий вид.

1) Я добавил скрытое поле ввода (называемое "действие" ) для каждой отдельной формы на странице. Например, это форма для обновления информации о пользователе, которая вытаскивает 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>

2) В моей логике "Вид" я могу различать формы, применяя префикс (на другие сообщения SO и Django docs). Затем, в зависимости от входящего "действия", я связываю только применимую форму с запросом 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) 

Кажется, хорошо работает, надеюсь, это правильный подход (?)

Ответ 2

Вы можете написать простой класс python, имитирующий API Form (по крайней мере, полезные части) и обернув ваши три формы. Обнаружить, какая форма была отправлена, - это просто добавить скрытый ввод с идентификатором формы в каждой форме (подсказка: использовать префиксы для ваших форм и использовать тот же префикс как идентификатор).

Другое решение состоит в том, чтобы вместо этого использовать простой вид на основе функций, но даже там я все еще использую тот же шаблон шаблона формы, насколько мне известно.