summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--django/contrib/gis/db/models/fields.py6
-rw-r--r--django/db/models/expressions.py2
-rw-r--r--tests/gis_tests/geoapp/test_expressions.py31
3 files changed, 39 insertions, 0 deletions
diff --git a/django/contrib/gis/db/models/fields.py b/django/contrib/gis/db/models/fields.py
index 7519b30fb2..4ded5b1b4e 100644
--- a/django/contrib/gis/db/models/fields.py
+++ b/django/contrib/gis/db/models/fields.py
@@ -312,6 +312,12 @@ class GeometryField(GeoSelectFormatMixin, BaseSpatialField):
"""
return connection.ops.get_distance(self, value, lookup_type)
+ def get_db_prep_value(self, value, connection, *args, **kwargs):
+ return connection.ops.Adapter(
+ super(GeometryField, self).get_db_prep_value(value, connection, *args, **kwargs),
+ **({'geography': True} if self.geography else {})
+ )
+
def from_db_value(self, value, expression, connection, context):
if value:
if not isinstance(value, Geometry):
diff --git a/django/db/models/expressions.py b/django/db/models/expressions.py
index ce685203ea..6bfbc36534 100644
--- a/django/db/models/expressions.py
+++ b/django/db/models/expressions.py
@@ -579,6 +579,8 @@ class Value(Expression):
val = self.output_field.get_db_prep_save(val, connection=connection)
else:
val = self.output_field.get_db_prep_value(val, connection=connection)
+ if hasattr(self._output_field, 'get_placeholder'):
+ return self._output_field.get_placeholder(val, compiler, connection), [val]
if val is None:
# cx_Oracle does not always convert None to the appropriate
# NULL type (like in case expressions using numbers), so we
diff --git a/tests/gis_tests/geoapp/test_expressions.py b/tests/gis_tests/geoapp/test_expressions.py
new file mode 100644
index 0000000000..c18d07f0e8
--- /dev/null
+++ b/tests/gis_tests/geoapp/test_expressions.py
@@ -0,0 +1,31 @@
+from unittest import skipUnless
+
+from django.contrib.gis.db.models import GeometryField, Value, functions
+from django.contrib.gis.geos import Point, Polygon
+from django.test import TestCase, skipUnlessDBFeature
+
+from ..utils import postgis
+from .models import City
+
+
+@skipUnlessDBFeature('gis_enabled')
+class GeoExpressionsTests(TestCase):
+ fixtures = ['initial']
+
+ def test_geometry_value_annotation(self):
+ p = Point(1, 1, srid=4326)
+ point = City.objects.annotate(p=Value(p, GeometryField(srid=4326))).first().p
+ self.assertEqual(point, p)
+
+ @skipUnlessDBFeature('supports_transform')
+ def test_geometry_value_annotation_different_srid(self):
+ p = Point(1, 1, srid=32140)
+ point = City.objects.annotate(p=Value(p, GeometryField(srid=4326))).first().p
+ self.assertTrue(point.equals_exact(p.transform(4326, clone=True), 10 ** -5))
+ self.assertEqual(point.srid, 4326)
+
+ @skipUnless(postgis, 'Only postgis has geography fields.')
+ def test_geography_value(self):
+ p = Polygon(((1, 1), (1, 2), (2, 2), (2, 1), (1, 1)))
+ area = City.objects.annotate(a=functions.Area(Value(p, GeometryField(srid=4326, geography=True)))).first().a
+ self.assertAlmostEqual(area.sq_km, 12305.1, 0)