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

Python 在Django模型中使用自定义实例属性的正确方法是什么?,python,django,django-models,Python,Django,Django Models,我想向Django模型的实例添加自定义属性。这些属性不应存储在数据库中。在任何其他类中,属性都只需通过\uuuu init\uuuu方法初始化 我已经看到了三种不同的方法,但没有一种是完全令人满意的。我想知道是否有更好的/更具pythonic/djangost风格的方法来做这件事 \uuuu init\uuuu方法:语法有点复杂,但它可以工作 from django.db.models import Model class Foo(Model): def __init__(self, *a

我想向Django模型的实例添加自定义属性。这些属性不应存储在数据库中。在任何其他类中,属性都只需通过
\uuuu init\uuuu
方法初始化

我已经看到了三种不同的方法,但没有一种是完全令人满意的。我想知道是否有更好的/更具pythonic/djangost风格的方法来做这件事

  • \uuuu init\uuuu
    方法:语法有点复杂,但它可以工作

    from django.db.models import Model
    
    class Foo(Model):
      def __init__(self, *args, **kwargs):
         super(Model, self).__init__(*args, **kwargs)
         self.bar = 1
    
  • 使用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
    
  • 使用实例方法而不是属性:作为默认行为引发常规异常有点令人不安

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

  • 在这三个选择中,第一个对我来说最不坏。你怎么认为?有其他选择吗?

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

    重写
    \uuuu init\uuuu
    是正确的方法

    有趣的是,我不知道@property decorator。但是你不觉得这很难看吗?如果你想有一个内置的默认值,而不是在代码的其他地方指定getattr,那就不会了。这只是在python中创建访问器方法的一种标准方法,因此,如果它很难看,我们只需要将其提交给Guido,作为对v3的改进:-PJust回到这个问题上,在我的指导下,我又学习了几年python(2013年!那时我还年轻天真…)。我想今天我会同意你的回答。
    @property
    方法非常类似于python。另一方面,django模型构造函数很少被重写。那么如何设置_bar的值呢?当您第一次询问例如instance.bar时,getattr将返回1,但它不会将_bar设置为1(或者至少在我使用python 3进行的测试中)