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
Вернуться на верх