Django: uma visão baseada em classe com mixins e método de despacho

Normalmente, eu uso umdispatch método de uma exibição baseada em classe para definir algumas variáveis iniciais ou adicionar alguma lógica com base nas permissões do usuário.

Por exemplo,

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 esperado: quando um usuário anônimo visita uma página, odispatch método deLoginRequiredMixin é chamado e, em seguida, redireciona o usuário para a página de login.

Mas se eu quiser adicionar algumas permissões para esta visualização ou definir algumas variáveis iniciais, por exemplo,

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)

em alguns casos, não funciona, porquedispatch Os métodos dos mixins, herdados pela visualização, ainda não foram chamados. Por exemplo, para poder solicitar permissões de usuário, tenho que repetir a validação 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 exemplo é simples, mas às vezes há uma lógica mais complicada em um mixin: verifica permissões, faz alguns cálculos e armazena em um atributo de classe, etc.

Por enquanto, eu resolvo isso copiando algum código do mixin (como no exemplo acima) ou copiando o código dodispatch método da view para outro mixin e herdando-o após o primeiro para executá-los em ordem (o que não é tão bonito, porque esse novo mixin é usado apenas por um view).

Existe alguma maneira adequada de resolver esses tipos de problemas?

questionAnswers(4)

yourAnswerToTheQuestion