Для чего используются миксины в Django
Что проверяют
Понимаете ли вы, как в Django собирается поведение class-based views из маленьких классов и как работает MRO в Python. Следом обычно спрашивают, в каком порядке указывать миксины и почему LoginRequiredMixin должен стоять первым.
Как отвечать
Миксин это класс с узкой порцией поведения, который сам по себе не используется, а подмешивается через множественное наследование. В Django они встречаются в нескольких местах:
- CBV:
ContextMixinдобавляетget_context_data(),TemplateResponseMixinрендеринг шаблона,SingleObjectMixinиMultipleObjectMixinполучение объекта или списка,FormMixinработу с формой. ДажеListViewсобран из таких кусков; - доступ:
LoginRequiredMixin,PermissionRequiredMixin,UserPassesTestMixinизdjango.contrib.auth.mixins. Проверку они делают вdispatch(), до вызоваget()илиpost(); - DRF:
ListModelMixin,CreateModelMixin,UpdateModelMixinв связке сGenericAPIView, из них же собранModelViewSet; - модели: роль миксина играет абстрактная модель с
class Meta: abstract = True, например с общими полямиcreated_atиupdated_at.
Главное, что стоит проговорить, это порядок. Python ищет метод по MRO слева направо, поэтому миксины пишут левее базового представления: class OrderList(LoginRequiredMixin, ListView). Переопределённый метод внутри миксина должен вызывать super(), тогда цепочка не рвётся:
def get_queryset(self): return super().get_queryset().filter(owner=self.request.user)
Такой миксин не знает о конкретной модели и работает с любым представлением, у которого есть get_queryset().
Где спотыкаются
Ставят миксин доступа правее базового класса. Тогда первым по MRO находится View.dispatch(), который super() не вызывает, проверка не срабатывает вовсе, и страница открывается анониму.
Не вызывают super() в переопределённом методе и молча выключают поведение других миксинов в цепочке, например фильтрацию или добавление контекста.
Строят иерархию из пяти или шести миксинов, которые читают атрибуты друг друга. Отлаживать это тяжело, и если миксину нужно много чужого состояния, логику лучше вынести в обычную функцию или сервис.