浏览代码

Refs #17635 -- Tested the Cast function in a geography to geometry context

Thanks Tim Graham for the review.
Claude Paroz 9 年之前
父节点
当前提交
1ee9c5b4a9
共有 2 个文件被更改,包括 30 次插入0 次删除
  1. 12 0
      docs/ref/contrib/gis/model-api.txt
  2. 18 0
      tests/gis_tests/geogapp/tests.py

+ 12 - 0
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>`_.

+ 18 - 0
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):
         """