【问题标题】:Setting field option based on return value of function根据函数的返回值设置字段选项
【发布时间】:2015-03-05 04:52:04
【问题描述】:

我有以下抽象类:

class BaseClass(models.Model):
 @property
 def is_a_null(self):
  return False

 field_a = models.CharField(max_length=1, null=is_a_null)

 class Meta:
  abtract = True

如果我从此类派生,则为 field_a 生成的 SQL 在字段旁边没有 NOT NULL。我想这样做是因为我希望派生类能够覆盖is_a_null

如果我使用null=False 而不是函数调用,生成的 SQL 会在字段旁边按预期显示NOT NULL

【问题讨论】:

  • 如果这可行,你可以试试:null=is_a_null.fget(is_a_null)
  • 对不起,做了一些不同的事情。

标签: python django django-models


【解决方案1】:

很遗憾,您的方法行不通。

属性和描述符的“魔力”发生在它们作为属性访问时。如果你直接引用它们——例如,在类定义期间——你只会得到一个property 对象。

class PropertyTest(object):
    @property
    def is_a_null(self):
        return False

    print(is_a_null)
    print(bool(is_a_null))

<property object at 0x02C0D5A0>
True

>>> PropertyTest().is_a_null
False

因此,您将is_a_null 属性对象传递给CharField 的构造函数,其计算结果为True

即使它按照您的意愿访问属性的 getter,这仍然不适用于继承。子类只是继承了已经定义的字段;你永远不能指望它重新访问你的财产。

如果 Django 的模型继承允许重新定义字段,您可以简单地在子类定义中创建一个新的 field_a 属性。不幸的是,这目前是不可能的(尽管this discussion 提出了这个功能很快就会被添加的可能性)。

您可以调整该线程中的补丁,或者从头开始创建自己的元类,尽管这两种解决方案都有些复杂。

【讨论】:

  • 常规方法似乎也是如此。不知道我为什么使用属性。
【解决方案2】:

我最终遵循了question 中的答案。例如:

class BaseClass(models.Model):
 field_a = models.CharField(max_length=1)

 class Meta:
  abtract = True

class DerivedClass(BaseClass):
 pass;

DerivedClass._meta.get_field('field_a').null = True

如果有办法在不访问_meta 的情况下做到这一点,那就太好了。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-10-10
    • 2016-06-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-19
    相关资源
    最近更新 更多