【问题标题】:Override save method for every class in models.Model覆盖models.Model中每个类的save方法
【发布时间】:2016-06-23 09:57:13
【问题描述】:

我需要获取每个继承 models.Model 的类来创建和更新字段。我可以通过向每个字段添加自定义保存方法来实现这一点,

def save(self, *args, **kwargs):
    if not self.id:
        self.created = timezone.now()
    self.modified = timezone.now()
    return super(`models.Model`, self).save(*args, **kwargs)

但这违反了 Don'tRepeatYourself 规则。

我已经尝试覆盖models.Model:

class LogModel(models.Model):
    created = models.DateTimeField(editable=False)
    updated = models.DateTimeField()

    def save(self, *args, **kwargs):
        if not self.id:
            self.created = timezone.now()
        self.updated = timezone.now()
        return super(LogModel, self).save(*args, **kwargs)

并使用 LogModel 而不是 models.Model,但这失败并出现错误 E006( 字段“x”与模型“y.logmodel”中的字段“x”冲突。

编辑

我的主要问题是如何为我的 models.py 中的所有模型添加自定义特定字段

【问题讨论】:

  • 请确保您的缩进在问题中正确显示,这样您就不会收到关于错误内容的反馈。 (对 Python 尤其重要。)另外,请详细说明“没有用”是什么意思。当你尝试时实际发生了什么?它根本没有保存吗?是默默失败了吗?有没有抛出异常?

标签: django django-models


【解决方案1】:

您的基础模型必须是抽象的:

class LogModel(models.Model):

    class Meta:
        abstract = True

    created = models.DateTimeField(editable=False)
    updated = models.DateTimeField()

    def save(self, force_insert=False, force_update=False, using=None, update_fields=None):
        # Use self._state.adding to check if this is a new instance,
        # ID not being empty is not a guarantee that the instance
        # exists in the database
        # and if `update_fields` is passed, you must add the fields to the
        # list or they won't be saved in the database.
        if force_insert or self._state.adding:
            self.created = timezone.now()
            if update_fields and 'created' not in update_fields:
                update_fields.append('created')
        self.updated = timezone.now()
        if update_fields and 'updated' not in update_fields:
            update_fields.append('updated')
        return super(LogModel, self).save(*args, **kwargs)

但是,如果您覆盖 save() 方法,这意味着它不能以任何形式进行编辑。如果这是你想要的,那么你最好使用auto_nowauto_now_add

class LogModel(models.Model):

    class Meta:
        abstract = True

    created = models.DateTimeField(auto_now_add=True)
    updated = models.DateTimeField(auto_now=True)

【讨论】:

    【解决方案2】:

    您可以在 Model 字段中定义 auto_now_addauto_now 参数,而不是覆盖 save 方法,例如:

    created = models.DateTimeField(auto_now_add=True)
    updated = models.DateTimeField(auto_now=True)
    

    有关这些参数的更多信息,您可以查看django docs

    【讨论】:

    • 我的主要问题是如何为所有模型添加特定字段。
    • 可以通过定义Abstract Model并在那里定义save方法并通过继承抽象类来创建所有模型。
    • 谢谢。答案很简单。
    【解决方案3】:

    可以通过定义Abstract Base Model并在那里定义save方法并通过从抽象类继承来创建所有模型来完成。例如

    class MyAbstractModel(models.Model):
        created = models.DateTimeField(editable=False)
        updated = models.DateTimeField()
    
        def save(self, *args, **kwargs):
            if self._state.adding:
                self.created = timezone.now()
            self.updated = timezone.now()
            return super(LogModel, self).save(*args, **kwargs)
    
        class Meta:
            abstract = True
    

    并从中创建子模型类:

    class Record(MyAbstractModel):
        pass
    

    【讨论】:

      【解决方案4】:

      不幸的是,在.save() 中使用update_fields 不会触发带有auto_now 的字段,所以我以这种方式覆盖了save 方法:

      class BaseModel(models.Model):
          class Meta:
              abstract = True
      
          created_at = models.DateTimeField(auto_now_add=True)
          updated_at = models.DateTimeField(auto_now=True)
      
          _base_update_fields = ['updated_at']
      
          def save(
              self, force_insert=False, force_update=False,
              using=None, update_fields=None
          ):
              _update_fields = None
      
              if update_fields is not None:
                  _update_fields = self._base_update_fields + update_fields
      
              super().save(
                  force_insert=force_insert, force_update=force_update,
                  using=using, update_fields=_update_fields
              )
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-09-28
        • 2021-11-21
        • 2018-12-08
        • 2018-10-12
        • 1970-01-01
        • 2011-05-28
        相关资源
        最近更新 更多