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