I have a view where I need to display information about a certain model instance hence I use a DetailView
. I also need that same view to handle a regular form (not a model form), both displaying the form on GET
and validating it on POST
. To do that, I am trying to use a FormView
however the combination of both view clases does not work:
class FooView(FormView, DetailView):
# configs here
In GET
(for simplicity of the question I will only show the issue with GET
since POST
has a different issue), it does not work because the form never gets added to the context. The reason has to do with method resolution order for that class:
>>> inspect.getmro(FooView)
(FooView,
django.views.generic.edit.FormView,
django.views.generic.detail.DetailView,
django.views.generic.detail.SingleObjectTemplateResponseMixin,
django.views.generic.base.TemplateResponseMixin,
django.views.generic.edit.BaseFormView,
django.views.generic.edit.FormMixin,
django.views.generic.detail.BaseDetailView,
django.views.generic.detail.SingleObjectMixin,
django.views.generic.base.ContextMixin,
django.views.generic.edit.ProcessFormView,
django.views.generic.base.View,
object)
Within the request, Django has to get the form and add it to the context. That happens in ProcessFormView.get
:
def get(self, request, *args, **kwargs):
"""
Handles GET requests and instantiates a blank version of the form.
"""
form_class = self.get_form_class()
form = self.get_form(form_class)
return self.render_to_response(self.get_context_data(form=form))
However the first class with the MRO which has get
defined is BaseDetailView
:
def get(self, request, *args, **kwargs):
self.object = self.get_object()
context = self.get_context_data(object=self.object)
return self.render_to_response(context)
As you can see the BaseDetailView.get
never calls super
hence the ProcessFormView.get
will never be called hence the the form will not be added to the context. This can be fixed by creating a mixin view where all these nuances for GET
and POST
can be taken care of however I do not feel it is a clean solution.
My question: is there any way of accomplishing what I want with Django's default CBV implementation without creating any mixins?