【问题标题】:What's the purpose of Django "deconstruct" model field function?Django“解构”模型字段函数的目的是什么?
【发布时间】:2016-01-01 17:36:24
【问题描述】:

为了开发自定义 Django 模型字段,我正在阅读文档。

我已经开发了我的自定义字段(几乎等于示例中的HandField:映射到 Python 类上的字段...唯一的区别是我继承自 models.CharField 而不是 @987654324 @)。

from external_library import ExternalClass

class ExternalClassField(models.CharField):
    description = "An ExternalClass field"

    def __init__(self, *args, **kwargs):
        kwargs['max_length'] = 14
        super(ExternalClassField, self).__init__(*args, **kwargs)

    def from_db_value(self, value, expression, connection, context):
        if value is None:
            return value
        return ExternalClass(value)

    def to_python(self, value):
        if isinstance(value, ExternalClass):
            return value

        if value is None:
            return value

        return ExternalClass(value)

    def get_prep_value(self, value):
        if value is None:
            return value

        if isinstance(value, ExternalClass):
            return value.to_string()

        return value

该字段的行为符合预期。但是,我被困在文档的这一部分:deconstruct() 函数。

特别是我不明白的是:

  • 解构函数的具体用途是什么?
  • 为什么我的字段即使没有它也能完美运行(即使我修改了init 参数)?
  • Django 如何以及何时调用解构函数?

不想一味的复制粘贴看不懂的代码,但是文档不清楚。

【问题讨论】:

  • 在迁移中用于序列化字段。

标签: python django


【解决方案1】:

deconstruct() 方法用于帮助执行系统无法自动处理的模型迁移。让我们来看一个调用 deconstruct 的场景。

假设我们有一些模型,我们向它添加了一个自定义字段。我们尝试使用python manage.py makemigrations 进行迁移。

我们遇到以下错误:

ValueError: Cannot serialize: Foo
There are some values Django cannot serialize into migration files.

原来已经有 a related ticket 被 Django 项目归档了,我们来看看吧。

一位核心开发人员回应说这是预期行为,因为我们的字段包含一个可调用对象。

所以,我们遗漏了文档中的一些内容。存储了一个可调用的值,由于某种原因无法自动迁移。我们能做什么?

嗯,除了告诉我们ValueErrormanage.py 还给了我们一个有用的文档链接:

在该页面上,向下滚动一点,直到我们到达关于 serializing values 的部分。

Django 可以序列化以下内容:

  • ...
  • 任何带有自定义 deconstruct() 方法的东西(见下文)
  • ...

好吧,让我们see below

您可以让 Django 序列化您自己的自定义类实例,方法是: 类一个 deconstruct() 方法。它不需要争论,应该 返回一个包含三件事的元组(路径、args、kwargs):

  • path 应该是类的 Python 路径,带有类名 包括在最后一部分(例如,myapp.custom_things.MyClass)。 如果您的课程在模块的顶层不可用,则它不是 可序列化的。
  • args 应该是要传递给的位置参数列表 你的类的 init 方法。此列表中的所有内容本身都应该是 可序列化的。
  • kwargs 应该是要传递给的关键字参数的字典 你的类的 init 方法。每个值本身都应该是 可序列化。

请注意,deconstruct() 方法与 __eq__() 密切相关,如文档所述:

为了防止每次运行 makemigrations 时都创建新的迁移,您还应该向装饰类添加 __eq__() 方法。该函数将被 Django 的迁移框架调用以检测状态之间的变化。

在我的例子中,错误是在不应该调用的值之后添加括号,但在许多情况下,您需要为迁移实现该解构方法。 (这是另一个useful link 有一个例子。)

【讨论】:

  • 我希望在 SO 上有更多这样的答案!
  • 出于某种原因,我没有接受答案。真的很抱歉:答案已接受。非常有见地和有用,谢谢!
猜你喜欢
  • 2015-01-20
  • 1970-01-01
  • 1970-01-01
  • 2019-10-18
  • 2017-01-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-01-27
相关资源
最近更新 更多