Django: una vista basada en clases con mixins y método de despacho

Normalmente uso undispatch método de una vista basada en clases para establecer algunas variables iniciales o agregar lógica basada en los permisos del usuario.

Por ejemplo,

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

Funciona como se esperaba: cuando un usuario anónimo visita una página, eldispatch método deLoginRequiredMixin se llama y luego redirige al usuario a la página de inicio de sesión.

Pero si quiero agregar algunos permisos para esta vista o establecer algunas variables iniciales, por ejemplo,

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)

en algunos casos no funciona porquedispatch Los métodos de los mixins, que la vista hereda, aún no se han llamado. Entonces, por ejemplo, para poder solicitar permisos de usuario, tengo que repetir la validación deLoginRequiredMixin:

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)

Este ejemplo es simple, pero a veces hay una lógica más complicada en un mixin: comprueba los permisos, hace algunos cálculos y los almacena en un atributo de clase, etc.

Por ahora lo resuelvo copiando algún código del mixin (como en el ejemplo anterior) o copiando el código deldispatch método de la vista a otro mixin y heredarlo después del primero para ejecutarlos en orden (que no es tan bonito, porque este nuevo mixin es usado solo por una vista).

¿Hay alguna manera adecuada para resolver este tipo de problemas?

Respuestas a la pregunta(4)

Su respuesta a la pregunta