一尘不染

Django:基于类的视图可以一次接受两种形式吗?

django

如果我有两种形式:

class ContactForm(forms.Form):
    name = forms.CharField()
    message = forms.CharField(widget=forms.Textarea)

class SocialForm(forms.Form):
    name = forms.CharField()
    message = forms.CharField(widget=forms.Textarea)

并想使用基于类的视图,并将两种形式都发送到模板,那有可能吗?

class TestView(FormView):
    template_name = 'contact.html'
    form_class = ContactForm

看来FormView一次只能接受一种形式。尽管在基于函数的视图中,我可以轻松地将两个表单发送到模板,然后在request.POST中检索这两个表单的内容。

variables = {'contact_form':contact_form, 'social_form':social_form }
return render(request, 'discussion.html', variables)

这是使用基于类的视图(通用视图)的限制吗?


阅读 389

收藏
2020-03-30

共2个答案

一尘不染

默认情况下,基于类的视图每个视图仅支持一个表单。但是还有其他方法可以满足您的需求。但是同样,这不能同时处理两种形式。这也适用于大多数基于类的视图以及常规形式。

views.py

class MyClassView(UpdateView):

template_name = 'page.html'
form_class = myform1
second_form_class = myform2
success_url = '/'

def get_context_data(self, **kwargs):
    context = super(MyClassView, self).get_context_data(**kwargs)
    if 'form' not in context:
        context['form'] = self.form_class(request=self.request)
    if 'form2' not in context:
        context['form2'] = self.second_form_class(request=self.request)
    return context

def get_object(self):
    return get_object_or_404(Model, pk=self.request.session['value_here'])

def form_invalid(self, **kwargs):
    return self.render_to_response(self.get_context_data(**kwargs))

def post(self, request, *args, **kwargs):
    self.object = self.get_object()
    if 'form' in request.POST:
        form_class = self.get_form_class()
        form_name = 'form'
    else:
        form_class = self.second_form_class
        form_name = 'form2'

    form = self.get_form(form_class)

    if form.is_valid():
        return self.form_valid(form)
    else:
        return self.form_invalid(**{form_name: form})

模板

{% csrf_token %} .........
{% csrf_token %} .........
2020-03-30
一尘不染

这是一个示例用法

class SignupLoginView(MultiFormsView):
    template_name = 'public/my_login_signup_template.html'
    form_classes = {'login': LoginForm,
                    'signup': SignupForm}
    success_url = 'my/success/url'

    def get_login_initial(self):
        return {'email':'dave@dave.com'}

    def get_signup_initial(self):
        return {'email':'dave@dave.com'}

    def get_context_data(self, **kwargs):
        context = super(SignupLoginView, self).get_context_data(**kwargs)
        context.update({"some_context_value": 'blah blah blah',
                        "some_other_context_value": 'blah'})
        return context

    def login_form_valid(self, form):
        return form.login(self.request, redirect_url=self.get_success_url())

    def signup_form_valid(self, form):
        user = form.save(self.request)
        return form.signup(self.request, user, self.get_success_url())

模板看起来像这样

<form class="login" method="POST" action="{% url 'my_view' %}">
    {% csrf_token %}
    {{ forms.login.as_p }}

    <button name='action' value='login' type="submit">Sign in</button>
</form>

<form class="signup" method="POST" action="{% url 'my_view' %}">
    {% csrf_token %}
    {{ forms.signup.as_p }}

    <button name='action' value='signup' type="submit">Sign up</button>
</form>

模板上要注意的重要事项是提交按钮。他们必须将其“名称”属性设置为“动作”,并且其“值”属性必须与“ form_classes”字典中为表单指定的名称相匹配。这用于确定已提交的单个表格。

2020-03-30