在Django模型中拥有自定义实例属性的正确方法是什么?

时间:2013-01-22 16:35:29

标签: python django django-models

我想将自定义属性添加到Django模型的实例中。这些属性不应存储在数据库中。在任何其他类中,属性将仅由__init__方法初始化。

我已经可以看到三种不同的方法,而且没有一种方法是完全令人满意的。我想知道是否有更好/更多的pythonic / djangoist方法来做它?

  1. Override __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
    
  4. 在这三个选择中,第一个看起来对我来说是最差的。你怎么看?还有其他选择吗?

2 个答案:

答案 0 :(得分:7)

我会使用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)

答案 1 :(得分:3)

覆盖__init__是正确的方法。