15

从 Django 升级1.9到后1.10,我体验到了 django-geolocation 包提供的字段的行为变化。

这是为1.10破坏行为的兼容性所做的更改:https ://github.com/philippbosch/django-geoposition/commit/689ff1651a858d81b2d82ac02625aae8a125b9c9

以前,如果您使用 初始化模型GeopositionField,然后立即访问该字段,您将返回一个Geoposition对象。现在您只需取回您在初始化时提供的字符串值。

您如何使用 Django 实现相同的行为1.10from_db_value是否需要覆盖另一种类似的方法才能调用to_python

4

1 回答 1

10

经过大量挖掘,事实证明,1.8自定义字段的行为发生了变化,to_python不再需要分配给字段。

https://docs.djangoproject.com/en/1.10/releases/1.8/#subfieldbase

新方法不像 SubfieldBase 那样在赋值时调用 to_python() 方法。如果您需要这种行为,请在您的项目中从 Django 的源代码重新实现 Creator 类。

这是一张 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

于 2016-09-13T13:14:46.017 回答