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?