我有一个django模型类,它将状态维护为一个简单的属性。我在类中添加了几个辅助属性来访问聚合状态 - 例如如果状态是is_live
等中的任何一个,则['closed', 'expired', 'deleted']
返回false。
因此,我的模型有一个is_属性集合,可以对对象的内部属性进行非常简单的查找。
我现在想要添加一个新属性is_complete
- 它在语义上与所有其他属性相同 - 对对象状态进行布尔检查 - 但是,此检查涉及加载依赖(一个 - to-many)子对象,检查它们的状态并根据结果报告 - 即这个属性实际上做了一些(多个)数据库查询,并处理结果。
那么,建模作为属性(使用@property
装饰器)是否仍然有效,或者我应该放弃装饰器并将其保留为方法?
使用属性的Pro是它在语义上与所有其他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背景,其中杰夫阿特伍德精心定义了分裂
“如果有任何机会可以产生沙漏,那肯定应该是一种方法。”
编辑2:对问题进行轻微更新 - 将它作为一种名为is_complete
的方法将是一个问题,以便混合属性和具有相似名称的方法 - 或者只是令人困惑? / p>
所以 - 它看起来像这样:
>>> m = MyModel()
>>> m.is_live
True
>>> m.is_complete()
False
答案 0 :(得分: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
请记住它"缓存"结果,所以首先执行计算,但后续使用现有结果。