16

When defining a FormView derived class:

class PrefsView(FormView):
    template_name = "prefs.html"
    form_class = MyForm         # What's wrong with this?
    def get(self,request):
        context = self.get_context_data()
        context['pagetitle'] = 'My special Title'
        context['form'] = MyForm    # Why Do I have to write this?
        return render(self.request,self.template_name,context)

I expected the line context['form'] = MyForm was not needed, since form_class is defined, but without it {{ form }} is not passed to template.
What I'm doing wrong?

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
tonjo
  • 1,394
  • 1
  • 14
  • 27

1 Answers1

19

In the context, form should be the instantiated form, not the form class. Defining the form_class is completely separate from including the instantiated form in the context data.

For the example you've given, I think you'd be better to override get_context_data instead of get.

def get_context_data(self, **kwargs):
    context = super(PrefsView, self).get_context_data(**kwargs)
    context['pagetitle'] = 'My special Title'
    return context
Alasdair
  • 298,606
  • 55
  • 578
  • 516
  • 1
    Yes, this is a good advice, but still does not answer the qeustion, why do I need that line? In several examples I see the use of form_class instead. – tonjo Oct 30 '13 at 16:01
  • In practice, you say defining `form_class` is completely separate from including the instantiated form in template. So maybe I didn't fully understand all this, for what purpose one should define `form_class`? – tonjo Oct 30 '13 at 16:23
  • 4
    You *don't* need that line if you don't override `get`. If you do, then you're preventing the default implementation from including the form, so of course you need to include it yourself. – Daniel Roseman Oct 30 '13 at 16:38
  • 5
    When using a `FormView`, [`form_class`](https://docs.djangoproject.com/en/dev/ref/class-based-views/mixins-editing/#django.views.generic.edit.FormMixin.form_class) defines what type of form to instantiate. The `get` method instantiates a a form, and includes it in the context. Since you are overriding `get`, you need to include `form` in the context as well. Because you seem to be overriding the `get` method to add an extra variable to the template context, I suggested overriding `get_context_data` instead - that way you don't need to worry about the other stuff that the `get` method does. – Alasdair Oct 30 '13 at 16:53
  • But I was returning `super()` :( Oh well, I guess it was some of the inherited classes' fault.. Thank you for this! – mccc Jul 28 '15 at 15:40