【问题标题】:Django: How to create a mixin to set common attributes for every model?Django:如何创建一个 mixin 来为每个模型设置公共属性?
【发布时间】:2021-08-16 16:49:36
【问题描述】:

我有一个模型 mixin,它设置了 created_atcreated_byupdated_atupdated_by,然后我将它们继承给我项目中的大多数模型。这个模型 mixin 工作正常。显然,由于auto_now_addauto_now,设置created_atmodified_at 非常容易。

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']

但是,我还想要创建一个 mixin(或者可能是子类)CreateViewUpdateViewcreated_byupdated_by 设置为 self.request.user 在使用这些 CBV 的任何地方(我猜修改get_form()form_valid())。我还需要创建一个类似的管理 mixin 来修改 save_model()

我从未创建过自定义 mixin,而且我发现/尝试过的东西都不起作用。例如,我通过修改 get_form() 使子类 CreateView 工作,但是我无法在我创建的各种 class ModelXCreate(...) 视图中进一步修改 get_form()

有谁知道我如何做到这一点?能够拥有这样的 mixin 并保持 DRY 是非常有用的。

【问题讨论】:

    标签: django django-models django-admin django-class-based-views


    【解决方案1】:

    您可以覆盖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)

    然后我们可以将这个mixin用于我们的CreateView/UpdateView

    class MyCreateView(CreateUpdateMixin, CreateView):
        # …
        pass
    
    class MyUpdateView(CreateUpdateMixin, UpdateView):
        # …
        pass

    【讨论】:

    • 您好,非常感谢。这实际上是我已经尝试过的,但是在 MyCreateView 的 get_form() 中(你已经通过了),随后的更改没有生效。 IE。它没有正确继承并被进一步修改。您能否编辑您的答案以包括如何继承和进一步修改 form_valid()?
    • @David:你在get_form() 中到底定义了什么?通常你应该只覆盖form_valid。请注意,您需要指定CreateUpdateMixin 之前 CreateView 作为父类。在确定 MRO 时,父母的顺序很重要
    猜你喜欢
    • 1970-01-01
    • 2011-08-26
    • 2016-11-26
    • 1970-01-01
    • 2018-04-18
    • 1970-01-01
    • 2013-02-06
    • 2016-11-04
    • 1970-01-01
    相关资源
    最近更新 更多