Normally, I use a dispatch
method of a class based view to set some initial variables or add some logic based on user's permissions.
For example,
from django.views.generic import FormView
from braces.views import LoginRequiredMixin
class GenerateReportView(LoginRequiredMixin, FormView):
template_name = 'reporting/reporting_form.html'
form_class = ReportForm
def get_form(self, form_class):
form = form_class(**self.get_form_kwargs())
if not self.request.user.is_superuser:
form.fields['report_type'].choices = [
choice for choice in form.fields['report_type'].choices
if choice[0] != INVOICE_REPORT
]
return form
It works as expected: when an anonymous user visits a pages, the dispatch
method of LoginRequiredMixin is called, and then redirects the user to the login page.
But if I want to add some permissions for this view or set some initial variables, for example,
class GenerateReportView(LoginRequiredMixin, FormView):
def dispatch(self, *args, **kwargs):
if not (
self.request.user.is_superuser or
self.request.user.is_manager
):
raise Http404
return super(GenerateReportView, self).dispatch(*args, **kwargs)
in some cases it doesn't work, because dispatch
methods of the mixins, that the view inherits, haven't been called yet. So, for example, to be able to ask for user's permissions, I have to repeat the validation from LoginRequiredMixin
:
class GenerateReportView(LoginRequiredMixin, FormView):
def dispatch(self, *args, **kwargs):
if self.request.user.is_authenticated() and not (
self.request.user.is_superuser or
self.request.user.is_manager
):
raise Http404
return super(GenerateReportView, self).dispatch(*args, **kwargs)
This example is simple, but sometimes there are some more complicated logic in a mixin: it checks for permissions, makes some calculations and stores it in a class attribute, etc.
For now I solve it by copying some code from the mixin (like in the example above) or by copying the code from the dispatch
method of the view to another mixin and inheriting it after the first one to execute them in order (which is not that pretty, because this new mixin is used only by one view).
Is there any proper way so solve these kind of problems?
super(GenerateReportView, self).dispatch(*args, **kwargs)
. then do the rest of the job inside the dispatch you are overriding – MiradorLoginRequiredMixin
returns aHttpResponseRedirect
object, so if we store it in a variable, it won't make a redirect to the login view until we return this variable at the end ofdispatch
method. – Arlon