Fixed #25499 -- Added the ability to pass an expression in distance lookups

Thanks Bibhas Debnath for the report and Tim Graham for the review.
This commit is contained in:
Claude Paroz 2015-10-06 22:05:53 +02:00
parent 4a7b58210d
commit 37d06cfc46
8 changed files with 84 additions and 33 deletions

View file

@ -21,6 +21,7 @@ class NamedModel(models.Model):
class SouthTexasCity(NamedModel):
"City model on projected coordinate system for South Texas."
point = models.PointField(srid=32140)
radius = models.IntegerField(default=10000)
class SouthTexasCityFt(NamedModel):
@ -31,6 +32,7 @@ class SouthTexasCityFt(NamedModel):
class AustraliaCity(NamedModel):
"City model for Australia, using WGS84."
point = models.PointField()
radius = models.IntegerField(default=10000)
class CensusZipcode(NamedModel):

View file

@ -6,7 +6,7 @@ from django.contrib.gis.db.models.functions import (
from django.contrib.gis.geos import GEOSGeometry, LineString, Point
from django.contrib.gis.measure import D # alias for Distance
from django.db import connection
from django.db.models import Q
from django.db.models import F, Q
from django.test import TestCase, ignore_warnings, skipUnlessDBFeature
from django.utils.deprecation import RemovedInDjango20Warning
@ -323,6 +323,31 @@ class DistanceTest(TestCase):
cities = self.get_names(qs)
self.assertEqual(cities, ['Adelaide', 'Hobart', 'Shellharbour', 'Thirroul'])
@skipUnlessDBFeature("supports_distances_lookups")
def test_distance_lookups_with_expression_rhs(self):
qs = SouthTexasCity.objects.filter(
point__distance_lte=(self.stx_pnt, F('radius')),
).order_by('name')
self.assertEqual(
self.get_names(qs),
['Bellaire', 'Downtown Houston', 'Southside Place', 'West University Place']
)
# With a combined expression
qs = SouthTexasCity.objects.filter(
point__distance_lte=(self.stx_pnt, F('radius') * 2),
).order_by('name')
self.assertEqual(len(qs), 5)
self.assertIn('Pearland', self.get_names(qs))
# With spheroid param
if connection.features.supports_distance_geodetic:
hobart = AustraliaCity.objects.get(name='Hobart')
qs = AustraliaCity.objects.filter(
point__distance_lte=(hobart.point, F('radius') * 70, 'spheroid'),
).order_by('name')
self.assertEqual(self.get_names(qs), ['Canberra', 'Hobart', 'Melbourne'])
@skipUnlessDBFeature("has_area_method")
@ignore_warnings(category=RemovedInDjango20Warning)
def test_area(self):