我有两个相关的模型:
class FirstModel(models.Model):
base_value = models.FloatField()
class SecondModel(models.Model):
parent = models.ForeignKey(FirstModel)
@property
def parent_value(self):
return self.parent.base_value
@property
def calculate(self):
return self.parent_value + 1
一般来说,SecondModel.calculate
主要用于与其相关的FirstModel
的上下文中。但是,有时我希望能够用一个临时值作为其parent_value
调用calculate
。像这样:
显然不能这样做,因为parent_value
是只读属性。我也有许多不同的模型类似于SecondModel,需要有这种能力。在
我考虑并尝试了几件事,但似乎都不太管用:
1)编写Django代理模型是可能的,但是对象的数量相当多,所以我会编写很多类似的代码。另外,似乎还有一个与重写属性相关的bug:https://code.djangoproject.com/ticket/16176。但看起来像这样:
class ModelProxy(SecondModel):
class Meta:
proxy = True
def __init__(self, temp_value):
self.parent_value = temp_value
2)重载实例上的parent_value
属性,如下所示:
foo = SecondModel()
setattr(foo, 'parent_value', 10)
但是不能这样做,因为属性是类的成员,而不是实例。我只希望为实例设置临时值
3)元类还是类生成器?似乎过于复杂。另外,我不确定如果我使用元类动态生成属于模型。模型. 我会遇到数据库表不同步的问题吗?在
4)使用适当的getter和setter重写属性?-也许解决方案是重写SecondModel以便设置属性?在
有什么建议吗?在
我相信mixin可以实现您想要的功能,并提供一种简单且可重用的方法来支持计算中的临时值。通过将下面的示例混合到您想要的每个模型中,您可以:
下面的代码应该达到你想要的-抱歉,我还没能测试它,但它应该是正确的-请让我知道如果有任何问题需要编辑。在
可以使用属性设置器:
我认为您可以使用下面显示的mixin
PropertyOverrideMixin
来完成所需的操作,如果某些属性值不可用,那么它将查找前缀为temp_
的相同属性。这将允许您提供临时值,当无法查找实际属性值时可以使用这些值。在下面是mixin,一些示例模型和一个单元测试来展示它是如何工作的。希望这能适应你的问题!最后值得一提的是,这里的属性可以与普通的对象属性互换,并且仍然可以正常工作。在
相关问题 更多 >
编程相关推荐