Django "deconstruct" 模型字段功能的目的是什么?

2024-05-29 10:30:34 发布

您现在位置:Python中文网/ 问答频道 /正文

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

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

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如何以及何时调用解构函数?在

我不想盲目地复制我不懂的粘贴代码,但是文档不清楚。在


Tags: djangofrom文档selfnonereturnifinit
1条回答
网友
1楼 · 发布于 2024-05-29 10:30:34

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

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

我们遇到以下错误:

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

原来已经有a related ticket与Django项目一起归档,让我们来看看。在

ticket-issue

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

ticket-resolution

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

好吧,除了告诉我们ValueErrormanage.py还为我们提供了一个有用的文档链接:

docs-link

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

Django can serialize the following:

  • ...
  • Anything with a custom deconstruct() method (see below)
  • ...

好吧,让我们see below

You can let Django serialize your own custom class instances by giving the class a deconstruct() method. It takes no arguments, and should return a tuple of three things (path, args, kwargs):

  • path should be the Python path to the class, with the class name included as the last part (for example, myapp.custom_things.MyClass). If your class is not available at the top level of a module it is not serializable.
  • args should be a list of positional arguments to pass to your class’ init method. Everything in this list should itself be serializable.
  • kwargs should be a dict of keyword arguments to pass to your class’ init method. Every value should itself be serializable.

注意,deconstruct()方法与__eq__()协同工作,如文档所述:

To prevent a new migration from being created each time makemigrations is run, you should also add a __eq__() method to the decorated class. This function will be called by Django’s migration framework to detect changes between states.

在我的例子中,错误是在一个不应该被调用的值后面加上括号,但是在很多情况下,您会希望为迁移实现解构方法。(这是另一个useful link的例子。)

相关问题 更多 >

    热门问题