summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClaude Paroz <claude@2xlibre.net>2016-04-10 19:55:29 +0200
committerClaude Paroz <claude@2xlibre.net>2016-04-12 21:14:45 +0200
commit1ee9c5b4a965aaec7ab230295dcd4b99e330ab03 (patch)
treef72844f4e91c31d4c026ff5482a5beaf053d43f2
parent1c30a6473df55c7efff71fd24f46c4b8d1ad5630 (diff)
Refs #17635 -- Tested the Cast function in a geography to geometry context
Thanks Tim Graham for the review.
-rw-r--r--docs/ref/contrib/gis/model-api.txt12
-rw-r--r--tests/gis_tests/geogapp/tests.py18
2 files changed, 30 insertions, 0 deletions
diff --git a/docs/ref/contrib/gis/model-api.txt b/docs/ref/contrib/gis/model-api.txt
index d5e1d79afa..f795ea7c20 100644
--- a/docs/ref/contrib/gis/model-api.txt
+++ b/docs/ref/contrib/gis/model-api.txt
@@ -235,6 +235,18 @@ available for geography columns:
* :lookup:`covers`
* :lookup:`intersects`
+If you need to use a spatial lookup or aggregate that doesn't support the
+geography type as input, you can use the
+:class:`~django.db.models.functions.Cast` database function to convert the
+geography column to a geometry type in the query::
+
+ from django.contrib.gis.db.models import PointField
+ from django.db.models.functions import Cast
+
+ Zipcode.objects.annotate(
+ geom=Cast('geography_field', PointField())
+ ).filter(geom__within=poly)
+
For more information, the PostGIS documentation contains a helpful section on
determining `when to use geography data type over geometry data type
<http://postgis.net/docs/manual-2.1/using_postgis_dbmanagement.html#PostGIS_GeographyVSGeometry>`_.
diff --git a/tests/gis_tests/geogapp/tests.py b/tests/gis_tests/geogapp/tests.py
index c314c93c5d..0711e26bc1 100644
--- a/tests/gis_tests/geogapp/tests.py
+++ b/tests/gis_tests/geogapp/tests.py
@@ -6,9 +6,12 @@ from __future__ import unicode_literals
import os
from unittest import skipUnless
+from django.contrib.gis.db import models
from django.contrib.gis.db.models.functions import Area, Distance
from django.contrib.gis.gdal import HAS_GDAL
from django.contrib.gis.measure import D
+from django.db import connection
+from django.db.models.functions import Cast
from django.test import TestCase, ignore_warnings, skipUnlessDBFeature
from django.utils._os import upath
from django.utils.deprecation import RemovedInDjango20Warning
@@ -113,6 +116,21 @@ class GeographyTest(TestCase):
class GeographyFunctionTests(TestCase):
fixtures = ['initial']
+ @skipUnlessDBFeature("supports_extent_aggr")
+ def test_cast_aggregate(self):
+ """
+ Cast a geography to a geometry field for an aggregate function that
+ expects a geometry input.
+ """
+ if not connection.ops.geography:
+ self.skipTest("This test needs geography support")
+ expected = (-96.8016128540039, 29.7633724212646, -95.3631439208984, 32.782058715820)
+ res = City.objects.filter(
+ name__in=('Houston', 'Dallas')
+ ).aggregate(extent=models.Extent(Cast('point', models.PointField())))
+ for val, exp in zip(res['extent'], expected):
+ self.assertAlmostEqual(exp, val, 4)
+
@skipUnlessDBFeature("has_Distance_function", "supports_distance_geodetic")
def test_distance_function(self):
"""