15

我有一个 django 模型类,它将状态维护为一个简单的属性。我在类中添加了几个辅助属性来访问聚合状态 - 例如is_live,如果状态是任何一个,则返回 false['closed', 'expired', 'deleted']等等。

因此,我的模型有一个 is_ 属性的集合,可以对对象的内部属性进行非常简单的查找。

我现在想添加一个新属性is_complete- 它在语义上与所有其他属性相同 - 对对象状态的布尔检查 - 但是,此检查涉及加载依赖(一对多)子对象,检查他们的状态和基于结果的报告——即这个属性实际上做了一些(不止一个)数据库查询,并处理结果。

那么,将其建模为属性(使用@property装饰器)仍然有效,还是应该放弃装饰器并将其保留为方法?

使用属性的优点是它在语义上与所有其他is_属性一致。

使用方法的优点在于它向其他开发人员表明这是具有更复杂实现的东西,因此应该谨慎使用(即不在for..循环内)。

from django.db import models

class MyModel(models.Model):

    state = CharField(default='new')

    @property
    def is_open(self):
        # this is a simple lookup, so makes sense as a property
        return self.state in ['new', 'open', 'sent']

    def is_complete(self):
        # this is a complex database activity, but semantically correct
        related_objects = self.do_complicated_database_lookup()
        return len(related_objects)==0

编辑:我最初来自 .NET 背景,Jeff Atwood 将拆分定义为

“如果代码有可能产生沙漏,那它绝对应该是一种方法。”

编辑 2:对问题的轻微更新 - 将它作为一个名为 的方法是否会有问题is_complete,以便混合具有相似名称的属性和方法 - 或者这只是令人困惑?

所以 - 它看起来像这样:

>>> m = MyModel()
>>> m.is_live
True
>>> m.is_complete()
False
4

1 回答 1

9

这样做是可以的,特别是如果您将使用以下模式:

class SomeClass(models.Model):
    @property
    def is_complete(self):
        if not hasattr(self, '_is_complete'):
            related_objects = self.do_complicated_database_lookup()
            self._is_complete = len(related_objects) == 0
        return self._is_complete

请记住,它“缓存”了结果,因此第一次执行进行计算,但随后使用现有结果。

于 2013-07-02T15:17:15.987 回答