Подклассификация 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
)