Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Update _check_geo_field to support lookup with reversed o2o relations…

…hip.

So that we can compute distance on the GeometryField of a related model.
  • Loading branch information...
commit d583c5bdd2317a9e1921c80d475f13eba8cb7f71 1 parent 45ef4ba
@pchiquet authored
View
12 django/contrib/gis/db/models/sql/where.py
@@ -74,15 +74,21 @@ def _check_geo_field(cls, opts, lookup):
fld_name = field_list.pop()
try:
- geo_fld = opts.get_field(fld_name)
+ geo_fld = opts.get_field_by_name(fld_name)[0]
+
# If the field list is still around, then it means that the
# lookup was for a geometry field across a relationship --
# thus we keep on getting the related model options and the
# model field associated with the next field in the list
# until there's no more left.
while len(field_list):
- opts = geo_fld.rel.to._meta
- geo_fld = opts.get_field(field_list.pop())
+ is_reverse_o2o = (not hasattr(geo_fld, 'rel') and geo_fld.field.unique)
+ if is_reverse_o2o:
+ model = geo_fld.model
+ else:
+ model = geo_fld.rel.to
+ opts = model._meta

opts seems to be unused here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
+ geo_fld = model._meta.get_field_by_name(field_list.pop())[0]
except (FieldDoesNotExist, AttributeError):
return False
View
9 django/contrib/gis/tests/geoapp/models.py
@@ -58,6 +58,15 @@ class Meta:
app_label = 'geoapp'
+class User(NamedModel):
+ pass
+
+
+class UserLocation(NamedModel):
+ user = models.OneToOneField(User)
+ point = models.PointField()
+
+
if not spatialite:
class Feature(NamedModel):
View
16 django/contrib/gis/tests/geoapp/test_regress.py
@@ -12,7 +12,7 @@
from django.test import TestCase
if HAS_GEOS:
- from .models import City, PennsylvaniaCity, State, Truth
+ from .models import City, PennsylvaniaCity, State, Truth, User, UserLocation
@skipUnless(HAS_GEOS and HAS_SPATIAL_DB, "Geos and spatial db are required.")
@@ -86,3 +86,17 @@ def test_boolean_conversion(self):
# verify values
self.assertEqual(val1, True)
self.assertEqual(val2, False)
+
+ def test_distance_on_lookup_with_reversed_o2o_relation(self):
+ "Testing distance with a reversed one to one relation lookup on a geographic field."
+ user = User.objects.create(name='test_user')
+ UserLocation.objects.create(name='Mansfield',
+ point='POINT(-77.071445 41.823881)',
+ user=user)
+ pnt = City.objects.get(name='Pueblo').point
+
+ # compute distance on User queryset by using related UserLocation.point field
+ users_with_distance = User.objects.all().distance(pnt,
+ field_name='userlocation__point')
+ self.assertEqual(len(users_with_distance), 1)
+ self.assertTrue(hasattr(users_with_distance[0], 'distance'))
@charettes

opts seems to be unused here.

Please sign in to comment.
Something went wrong with that request. Please try again.