From 72e4a77e2aa390a102df4fe4aa8acad02a97b6c6 Mon Sep 17 00:00:00 2001 From: Johannes Date: Wed, 14 Sep 2016 12:53:08 +0100 Subject: [PATCH 1/2] Add failing test --- geoposition/tests/test_geoposition.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/geoposition/tests/test_geoposition.py b/geoposition/tests/test_geoposition.py index 86862a7..1dbaa0a 100644 --- a/geoposition/tests/test_geoposition.py +++ b/geoposition/tests/test_geoposition.py @@ -52,3 +52,7 @@ def test_db_value_to_python_object(self): obj = PointOfInterest.objects.create(name='Foo', address='some where', city='city', zipcode='12345', position=Geoposition(52.5, 13.4)) poi = PointOfInterest.objects.get(id=obj.id) self.assertIsInstance(poi.position, Geoposition) + + def test_value_conversion_on_assignment(self): + obj = PointOfInterest(name='Foo', address='some where', city='city', zipcode='12345', position='52.5,13.4') + self.assertEqual(obj.position, Geoposition(52.5, 13.4)) From b8f010d932418b3646366cf16a9351128263b1c1 Mon Sep 17 00:00:00 2001 From: Johannes Date: Wed, 14 Sep 2016 12:55:02 +0100 Subject: [PATCH 2/2] Restore value conversion on assignment behaviour --- geoposition/fields.py | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/geoposition/fields.py b/geoposition/fields.py index 9fe86bc..d34312e 100644 --- a/geoposition/fields.py +++ b/geoposition/fields.py @@ -9,6 +9,26 @@ from .forms import GeopositionField as GeopositionFormField +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) + + class GeopositionField(models.Field): description = _("A geoposition (latitude and longitude)") @@ -40,6 +60,10 @@ def to_python(self, value): return Geoposition(latitude, longitude) + def contribute_to_class(self, cls, name): + super(GeopositionField, self).contribute_to_class(cls, name) + setattr(cls, name, CastOnAssignDescriptor(self)) + def from_db_value(self, value, expression, connection, context): return self.to_python(value)