Django: Как создать миксин для установки общих атрибутов для каждой модели?
У меня есть модель mixin, которая устанавливает created_at, created_by, updated_at и updated_by, которую я затем наследую для большинства моделей в моем проекте. Этот модельный миксин работает нормально. Очевидно, что установить created_at и modified_at очень просто благодаря auto_now_add и auto_now.
class Timestampable(models.Model):
created_at = models.DateTimeField(
auto_now_add=True,
db_index=True,
verbose_name=_('created at')
)
created_by = models.ForeignKey(settings.AUTH_USER_MODEL, null=True, related_name="created%(app_label)s_%(class)s_related", on_delete=models.SET_NULL)
updated_at = models.DateTimeField(
auto_now=True,
db_index=True,
verbose_name=_('updated at')
)
updated_by = models.ForeignKey(settings.AUTH_USER_MODEL, null=True, related_name="updated%(app_label)s_%(class)s_related", on_delete=models.SET_NULL)
class Meta:
abstract = True
ordering = ['-created_at']
Но я хочу также создать миксин (или, возможно, подкласс) CreateView и UpdateView для установки created_by и updated_by в качестве self.request.user везде, где используются эти CBV (я предполагаю, путем изменения get_form() или form_valid()). Мне также нужно будет создать аналогичный админ-миксин для изменения save_model().
Я никогда не создавал пользовательский миксин, и то, что я нашел/пробовал, не работает. Например, я добился работы подклассификации CreateView, изменив get_form(), но затем я не смог дальше изменять get_form() в различных class ModelXCreate(...) представлениях, которые я создал.
Кто-нибудь знает, как я могу этого добиться? Было бы очень полезно иметь такой миксин и сохранить все DRY.
Вы можете переопределить метод form_valid и таким образом работать с:
from django.contrib.auth.mixins import LoginRequiredMixin
class CreateUpdateMixin(LoginRequiredMixin):
def form_valid(self, form):
instance = form.instance
if instance.pk is None: # created
instance.created_by = instance.updated_by = self.request.user
else: # updated
instance.updated_by = self.request.user
return super().form_valid(form)
Тогда мы можем использовать этот миксин для наших CreateView/UpdateView:
class MyCreateView(CreateUpdateMixin, CreateView):
# …
pass
class MyUpdateView(CreateUpdateMixin, UpdateView):
# …
pass