为了开发自定义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()
方法用于帮助执行无法由系统自动处理的模型迁移.让我们来看看解构将被调用的场景.
假设我们有一些模型,我们为它添加了一个自定义字段.我们尝试迁移python manage.py makemigrations
.
我们遇到以下错误:
ValueError: Cannot serialize: Foo There are some values Django cannot serialize into migration files.
事实证明,已经有一个与 Django项目一起提交的相关票证,让我们检查一下.
其中一个核心开发人员回应说这是预期的行为,因为我们的字段包含一个可调用的.
所以,我们错过了文档中的内容.存储了可调用的值,并且由于某种原因无法自动迁移.我们能做什么?
好吧,除了告诉我们之外ValueError
,manage.py
还给了我们一个有用的文档链接:
进入该页面后,向下滚动一下,直到我们进入有关序列化值的部分.
Django可以序列化以下内容:
...
任何带有自定义deconstruct()方法的东西(见下文)
...
好吧,让我们看看如下:
您可以让Django通过为类提供deconstruct()方法来序列化您自己的自定义类实例.它不需要任何参数,并且应该返回三个元素的元组(path,args,kwargs):
path应该是类的Python路径,包含类名作为最后一部分(例如,myapp.custom_things.MyClass).如果您的类在模块的顶层不可用,则它不可序列化.
args应该是一个传递给类的init方法的位置参数列表.此列表中的所有内容本身都应该是可序列化的.
kwargs应该是一个关键字参数的字典,以传递给你的类的init方法.每个值本身都应该是可序列化的.
请注意,deconstruct()方法与__eq__()
文档中所述的一起工作:
为了防止每次运行makemigrations时都创建新的迁移,您还应该向装饰的类添加__eq __()方法.Django的迁移框架将调用此函数来检测状态之间的变化.
在我的例子中,错误是在一个本不应该被调用的值之后添加括号,但在许多情况下,您将需要为迁移实现该解构方法.(这是另一个有用的链接,有一个例子.)