在Django模型中如何正确添加自定义实例属性?

13 投票
2 回答
4160 浏览
提问于 2025-04-17 13:21

我想给Django模型的实例添加一些自定义属性。这些属性不需要存储在数据库里。在其他类里,这些属性通常会通过__init__方法来初始化。

我已经想到了三种不同的方法来实现这个目标,但都不是特别满意。我在想有没有更好、更符合Python或Django风格的方法呢?

  1. 重写 __init__方法:语法有点复杂,但可以实现。

    from django.db.models import Model
    
    class Foo(Model):
      def __init__(self, *args, **kwargs):
         super(Model, self).__init__(*args, **kwargs)
         self.bar = 1
    
  2. 使用Django的post_init信号:这样做会把类的代码放到类定义之外,这样看起来不太容易理解。

    from django.dispatch import receiver
    from django.db.models.signals import post_init
    @receiver(post_init, sender=Foo)
        def user_init(sender, instance, *args, **kwargs):
          instance.bar = 1
    
  3. 用实例方法代替属性:默认情况下抛出一个通用异常,这样的行为有点让人不安。

    class Foo(Model):
      def bar(self):
        try:
          return self.bar
        except:
          self.bar = 1
        return self.bar
    

在这三种选择中,我觉得第一种是最不糟糕的。你觉得呢?有没有其他的选择?

2 个回答

9

我会使用Python中的属性装饰器

class Foo(Model):
    @property
    def bar(self):
        if not hasattr(self, '_bar'):
            self._bar = 1

        return self._bar

这样你就可以像访问属性一样来使用它,而不是用()来调用一个函数

你甚至可以更简单一点,把备用方案直接内置,而不是单独存储

class Foo(Model):
    @property
    def bar(self):
        return getattr(self, '_bar', 1)
4

重写 __init__ 是正确的方法。

撰写回答