在 Django >=1.10 中初始化(未从数据库加载)后立即访问字段时,如何进行自定义模型字段调用 to_python?
How do I make a custom model Field call to_python when the field is accessed immediately after initialization (not loaded from DB) in Django >=1.10?
从 Django 1.9
升级到 1.10
后,我发现 django-geolocation 包提供的字段的行为发生了变化。
这是为 1.10
兼容性所做的更改,破坏了行为:https://github.com/philippbosch/django-geoposition/commit/689ff1651a858d81b2d82ac02625aae8a125b9c9
以前,如果您使用 GeopositionField
初始化模型,然后立即访问该字段,您会得到一个 Geoposition
对象。现在您只需取回您在初始化时提供的字符串值。
如何使用 Django 1.10
实现相同的行为?是否需要重写 from_db_value
之类的其他方法才能调用 to_python
?
经过大量挖掘后发现,在 1.8
中,自定义字段的行为发生了变化,因此 to_python
不再在分配给字段时被调用。
https://docs.djangoproject.com/en/1.10/releases/1.8/#subfieldbase
The new approach doesn’t call the to_python() method on assignment as was the case with SubfieldBase. If you need that behavior, reimplement the Creator class from Django’s source code in your project.
这是一张 Django 票证,其中包含有关此更改的更多讨论:https://code.djangoproject.com/ticket/26807
所以为了保留旧的行为,你需要做这样的事情:
class CastOnAssignDescriptor(object):
"""
A property descriptor which ensures that `field.to_python()` is called on _every_ assignment to the field.
This used to be provided by the `django.db.models.subclassing.Creator` class, which in turn
was used by the deprecated-in-Django-1.10 `SubfieldBase` class, hence the reimplementation here.
"""
def __init__(self, field):
self.field = field
def __get__(self, obj, type=None):
if obj is None:
return self
return obj.__dict__[self.field.name]
def __set__(self, obj, value):
obj.__dict__[self.field.name] = self.field.to_python(value)
然后将此添加到自定义字段:
def contribute_to_class(self, cls, name):
super(MyField, self).contribute_to_class(cls, name)
setattr(cls, name, CastOnAssignDescriptor(self))
解决方案取自此拉取请求:https://github.com/hzdg/django-enumfields/pull/61
从 Django 1.9
升级到 1.10
后,我发现 django-geolocation 包提供的字段的行为发生了变化。
这是为 1.10
兼容性所做的更改,破坏了行为:https://github.com/philippbosch/django-geoposition/commit/689ff1651a858d81b2d82ac02625aae8a125b9c9
以前,如果您使用 GeopositionField
初始化模型,然后立即访问该字段,您会得到一个 Geoposition
对象。现在您只需取回您在初始化时提供的字符串值。
如何使用 Django 1.10
实现相同的行为?是否需要重写 from_db_value
之类的其他方法才能调用 to_python
?
经过大量挖掘后发现,在 1.8
中,自定义字段的行为发生了变化,因此 to_python
不再在分配给字段时被调用。
https://docs.djangoproject.com/en/1.10/releases/1.8/#subfieldbase
The new approach doesn’t call the to_python() method on assignment as was the case with SubfieldBase. If you need that behavior, reimplement the Creator class from Django’s source code in your project.
这是一张 Django 票证,其中包含有关此更改的更多讨论:https://code.djangoproject.com/ticket/26807
所以为了保留旧的行为,你需要做这样的事情:
class CastOnAssignDescriptor(object):
"""
A property descriptor which ensures that `field.to_python()` is called on _every_ assignment to the field.
This used to be provided by the `django.db.models.subclassing.Creator` class, which in turn
was used by the deprecated-in-Django-1.10 `SubfieldBase` class, hence the reimplementation here.
"""
def __init__(self, field):
self.field = field
def __get__(self, obj, type=None):
if obj is None:
return self
return obj.__dict__[self.field.name]
def __set__(self, obj, value):
obj.__dict__[self.field.name] = self.field.to_python(value)
然后将此添加到自定义字段:
def contribute_to_class(self, cls, name):
super(MyField, self).contribute_to_class(cls, name)
setattr(cls, name, CastOnAssignDescriptor(self))
解决方案取自此拉取请求:https://github.com/hzdg/django-enumfields/pull/61