Подклассификация TemplateView с помощью миксинов - плохая идея?

У меня есть несколько представлений "Listing", которые очень похожи, и я чувствую, что неоправданно повторяюсь. Подклассификация кажется выходом, но я уже сталкивался с проблемами при подклассификации вещей в Django, поэтому я хотел бы спросить, прежде чем делать это.

Если у меня есть 2 представления, как это, которые используют один и тот же шаблон, переменную message и разные наборы запросов:

class MyGiverView(LoginRequiredMixin, TemplateView):

    template_name = "generic_listings.html"
    message = ""

    def get_context_data(self, **kwargs):

        context = super().get_context_data(**kwargs)
        context["list_of_stuff"] = MyModel.objects.filter(
            giver=self.request.user,
            status=1,
        )
        context["message"] = self.message

        return context

class MyTakerView(LoginRequiredMixin, TemplateView):

    template_name = "generic_listings.html" # this hasn't changed
    message = ""

    def get_context_data(self, **kwargs):

        context = super().get_context_data(**kwargs)
        context["list_of_stuff"] = MyModel.objects.filter(
            taker=self.request.user, # this has changed
            status__in=(1,2,3), # this has changed
        )
        context["message"] = self.message # this hasn't changed

        return context

Не испорчу ли я его, создав базовый класс типа:

class MyBaseView(LoginRequiredMixin, TemplateView):

    template_name = "generic_listings.html"
    
    def get_context_data(self, **kwargs):

        context = super().get_context_data(**kwargs)
        context["list_of_stuff"] = self.qs
        context["message"] = self.message

        return context

И использую его в своих представлениях в таком виде:

class MyGiverView(MyBaseView):

  qs = MyModel.objects.filter(
    giver=self.request.user,
    status=1,
  )
  message = ""

class MyTakerView(MyBaseView):

  qs = MyModel.objects.filter(
    taker=self.request.user,
    status__in=(1,2,3),
  )
  message = ""

Он более сухой, но я не уверен в последствиях относительно того, что происходит "под капотом".

Вместо того, чтобы создавать базовый класс, лучше создать класс-миксин для того, что вам нужно.

Кроме того, использование ListView было бы лучше для того, что вам нужно.

Вот мое предложение:

class InjectMessageMixin:
    message = ""

    # Always use this method to get the message. This allows user
    # to override the message in case it is needed to do on a request
    # basis (more dynamic) instead of using the class variable "message".
    def get_message(self):
        return self.message

    def get_context_data(self, **kwargs):
        # This line is super important so you can normally use
        # this mixin with other CBV classes.
        context = super().get_context_data(**kwargs)
        context.update({'message': self.get_message()})

        return context


class MyGiverView(LoginRequiredMixin, InjectMessageMixin, ListView):
    # Even though this doesn't change I would keep it repeated. Normally,
    # templates are not reused between views so I wouldn't say it's necessary
    # to extract this piece of code.
    template_name = "generic_listings.html"
    message = "giver message"

    def get_queryset(self):
        return MyModel.objects.filter(
            giver=self.request.user,
            status=1,
        )


class MyTakerView(LoginRequiredMixin, InjectMessageMixin, ListView):
    # Even though this doesn't change I would keep it repeated. Normally,
    # templates are not reused between views so I wouldn't say it's necessary
    # to extract this piece of code.
    template_name = "generic_listings.html"
    message = "taker message"

    def get_queryset(self, **kwargs):
        return MyModel.objects.filter(
            taker=self.request.user, # this has changed
            status__in=(1,2,3), # this has changed
        )
Вернуться на верх