为了开发自定义 Django 模型字段,我正在阅读文档。
我已经开发了我的自定义字段(这几乎等于示例的自定义字段,HandField
:一个映射到 Python 类的字段......唯一的区别是我继承自 models.CharField
而不是 models.Field
)。
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 如何以及何时调用 deconstruct 函数?
我不想盲目复制粘贴我看不懂的代码,但文档也不清楚。
最佳答案
deconstruct()
方法用于帮助执行系统无法自动处理的模型迁移。让我们来看一个 deconstruct 被调用的场景。
假设我们有一些模型,我们向它添加了一个自定义字段。我们尝试使用 python manage.py makemigrations
进行迁移。
我们遇到以下错误:
ValueError: Cannot serialize: Foo
There are some values Django cannot serialize into migration files.
原来已经有a related ticket了已提交给 Django 项目,让我们检查一下。
其中一位核心开发人员回应说这是有意为之的行为,因为我们的字段包含一个可调用对象。
因此,我们在文档中遗漏了一些内容。存储了一个可调用值,但由于某种原因无法自动迁移。我们能做什么?
嗯,除了告诉我们有关 ValueError
的信息,manage.py
还为我们提供了一个有用的文档链接:
进入该页面后,向下滚动一点,直到我们到达关于 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。)
关于python - Django "deconstruct"模型字段函数的用途是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34558397/