welworx
welworx

Reputation: 370

django: subclass FormView twice and override form_class

Im trying to build a FormView for an app that needs to be subclassed afterwards. Sadly I was not able to set the formclass by the subclass.

My Code:

class EventCreateView(FormView):
    template_name='Events/add_event_form.html'
    success_url = reverse_lazy('events_list')
    form_class = None  # replaced by __init__ function

    def __init__(self, *args, **kwargs):
        self.form_class=EventForm
        return super(EventCreateView, self).__init__(*args, **kwargs)

    #other functions, not shown here .. 


class TrainingCreateView(EventCreateView):
    def __init__(self, *args, **kwargs):
        self.form_class=TrainingForm
        return super(TrainingCreateView, self).__init__(*args, **kwargs)

urls.py:

 urlpatterns = patterns('',
     url(r'event/event/add/$', EventCreateView.as_view(), name='event_add'),
     url(r'event/training/add/$', TrainingCreateView.as_view(), name='training_add'),
 )

What am I doing wrong?

Upvotes: 1

Views: 711

Answers (2)

Lorenzo Peña
Lorenzo Peña

Reputation: 2263

Try this instead:

class EventCreateView(FormView):
    template_name='Events/add_event_form.html'
    success_url = reverse_lazy('events_list')
    form_class = EventForm

    ...

class TrainingCreateView(EventCreateView):
    form_class = TrainingForm

Upvotes: 3

Alasdair
Alasdair

Reputation: 308799

This doesn't work for the TrainingCreateView because the __init__ view does the following

  1. It sets self.form_class = TrainingForm
  2. super(TrainingCreateView, self).__init__(*args, **kwargs) calls the __init__ of EventCreateView ...
  3. Which sets self.formclass = EventForm

You can get around this by changing the order of your __init_ method. Note that the method doesn't have to return anything.

class TrainingCreateView(EventCreateView):
    def __init__(self, *args, **kwargs):
        super(TrainingCreateView, self).__init__(*args, **kwargs)
        self.form_class = TrainingForm

However, from the code you've written, it is not clear why you need to set self.form_class in the __init__ method, rather than just setting it as a class attribute. If you need to set it dynamically, a better option might be to override get_form_class instead.

Upvotes: 2

Related Questions