Commit 1ee9c5b4 authored by Claude Paroz's avatar Claude Paroz
Browse files

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

Thanks Tim Graham for the review.
parent 1c30a647
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
@@ -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
Original line number Diff line number Diff line
@@ -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):
        """