Skip to content

Commit

Permalink
Fixed #27962 -- Allowed lookups on Area annotations.
Browse files Browse the repository at this point in the history
  • Loading branch information
sir-sigurd authored and timgraham committed Mar 23, 2017
1 parent e9149d3 commit 85c68ac
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 1 deletion.
13 changes: 12 additions & 1 deletion django/contrib/gis/db/models/sql/conversion.py
Expand Up @@ -7,6 +7,7 @@
from django.contrib.gis.db.models.fields import GeoSelectFormatMixin
from django.contrib.gis.geometry.backend import Geometry
from django.contrib.gis.measure import Area, Distance
from django.db import models


class BaseField:
Expand All @@ -19,11 +20,21 @@ def select_format(self, compiler, sql, params):
return sql, params


class AreaField(BaseField):
class AreaField(models.FloatField):
"Wrapper for Area values."
def __init__(self, area_att=None):
self.area_att = area_att

def get_prep_value(self, value):
if not isinstance(value, Area):
raise ValueError('AreaField only accepts Area measurement objects.')
return value

def get_db_prep_value(self, value, connection, prepared=False):
if value is None or not self.area_att:
return value
return getattr(value, self.area_att)

def from_db_value(self, value, expression, connection, context):
if connection.features.interprets_empty_strings_as_nulls and value == '':
value = None
Expand Down
13 changes: 13 additions & 0 deletions tests/gis_tests/geoapp/test_functions.py
Expand Up @@ -264,6 +264,19 @@ def test_area_with_regular_aggregate(self):
result = result.sq_m
self.assertAlmostEqual((result - c.mpoly.area) / c.mpoly.area, 0)

@skipUnlessDBFeature("has_Area_function")
def test_area_lookups(self):
# Create projected country objects for the test to work on all backends.
CountryWebMercator.objects.bulk_create(
CountryWebMercator(name=c.name, mpoly=c.mpoly.transform(3857, clone=True))
for c in Country.objects.all()
)
qs = CountryWebMercator.objects.annotate(area=functions.Area('mpoly'))
self.assertEqual(qs.get(area__lt=Area(sq_km=500000)), CountryWebMercator.objects.get(name='New Zealand'))

with self.assertRaisesMessage(ValueError, 'AreaField only accepts Area measurement objects.'):
qs.get(area__lt=500000)

@skipUnlessDBFeature("has_MakeValid_function")
def test_make_valid(self):
invalid_geom = fromstr('POLYGON((0 0, 0 1, 1 1, 1 0, 1 1, 1 0, 0 0))')
Expand Down

0 comments on commit 85c68ac

Please sign in to comment.