【问题标题】:What is the right way to have custom instance attributes in Django models?在 Django 模型中拥有自定义实例属性的正确方法是什么?
【发布时间】:2013-01-22 16:35:29
【问题描述】:

我想为 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
    

在这三个选择中,第一个对我来说似乎是最差的。你怎么看?有什么选择吗?

【问题讨论】:

    标签: python django django-models


    【解决方案1】:

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

    【讨论】:

    • 有趣,我不知道@property 装饰器。但是你不觉得这很丑吗?
    • 如果你想拥有一个内置的默认值而不是在代码中的其他任何地方指定 getattr,则不是。这只是在 python 中创建访问器方法的标准方式,所以如果它很难看,我们只需要将它作为 v3 的改进带到 Guido :-P
    • 刚回到这个问题,我又用了几年的 Python(2013 年!那时我还年轻天真……)。我想今天我会接受你的回答。 @property 方法非常符合 Python 风格。另一方面,django 模型构造函数很少被覆盖。
    • 你将如何设置 _bar 的值?了解当您第一次询问 instance.bar 时 getattr 将返回 1,但它不会将 _bar 设置为 1(或至少在我使用 python 3 进行的测试中)
    【解决方案2】:

    覆盖__init__ 是正确的方法。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-02-11
      • 2010-11-02
      • 1970-01-01
      • 2016-07-04
      • 1970-01-01
      相关资源
      最近更新 更多