Python/Django - Django 模型的动态属性重载

标签 python django oop

我有两个相关模型:

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。像这样的事情:

foo = SecondModel()
# would look in the database for the related FirstModel and add 1 to its base_value
foo.calculate

foo.parent_value = 10
foo.calculate      # should return 11

显然您不能执行此操作,因为 parent_value 是只读属性。我还有许多类似于 SecondModel 的不同模型需要具备这种功能。

我考虑并尝试了几件事,但似乎没有一个完全有效:

1) 编写 Django 代理模型 - 可能,但对象的数量相当多,所以我会编写很多类似的代码。此外,似乎存在与覆盖属性相关的错误: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) 元类还是类生成器? - 看起来过于复杂。另外,我不确定如果我使用元类动态生成 models.Model 子级的类会发生什么。我会遇到数据库表不同步的问题吗?

4) 使用适当的 getter 和 setter 重写属性? - 也许解决方案是重写 SecondModel 以便可以设置属性?

有什么建议吗?

最佳答案

我相信 mixin 可以实现您想要做的事情,并提供一种简单且可重用的方式来支持计算中的临时值。通过将以下示例混合到您想要此行为的每个模型中,您可以:

  • 为每个模型设置临时父值
  • 调用calculate时,会检查是否有可用的属性parent_value,如果没有,则在计算中使用临时父值。

下面的代码应该可以实现您正在寻找的内容 - 抱歉,我还无法测试它,但它应该是正确的 - 如果有任何问题需要编辑,请告诉我。

class CalculateMixin(object):

    @property
    def temp_parent_value(self):
        return self._temp_parent_value

    @temp_parent_value.setter
    def temp_parent_value(self, value):
        self._temp_parent_value = value

    @property
    def calculate(self):
        parent_value = self.parent_value if self.parent_value else self.temp_parent_value
        return parent_value + 1


class SecondModel(models.Model, CalculateMixin):
    parent = models.ForeignKey(FirstModel)

    self.temp_parent_value = 'Whatever value you desire'

    @property
    def parent_value(self):
        return self.parent.base_value

关于Python/Django - Django 模型的动态属性重载,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17293908/

相关文章:

python - 使用 Django channel 进行 session 身份验证

python - Django:将结果从两个 mysql 表返回到 JSON

python - python中两个浮点值的比较

python - 尝试创建数组时继续使用 numpy 获取 ValueError

python - 为什么要使用 tensorflow gfile? (对于文件 I/O)

python - Django 直接链接到文件

java - 如何将对外部类的引用传递给内部类中的方法? (或者如何将 "this"传递给内部类?)

ruby - 我怎么知道方法期望的参数类型?

c# - 添加一个参数,还是创建一个新方法?

python - 为什么在 Python 中为 msvcr100 调用 kernel32.GetModuleHandleA() 失败?