Removed some more hardcoded backends in GIS tests
Refs #22632. Thanks Tim Graham for the review.
This commit is contained in:
parent
5675eb371f
commit
60428ed5db
|
@ -16,6 +16,9 @@ class BaseSpatialFeatures(object):
|
|||
# Does the database contain a SpatialRefSys model to store SRID information?
|
||||
has_spatialrefsys_table = True
|
||||
|
||||
# Reference implementation of 3D functions is:
|
||||
# http://postgis.net/docs/PostGIS_Special_Functions_Index.html#PostGIS_3D_Functions
|
||||
supports_3d_functions = False
|
||||
# Does the database support SRID transform operations?
|
||||
supports_transform = True
|
||||
# Do geometric relationship operations operate on real shapes (or only on bounding boxes)?
|
||||
|
@ -29,24 +32,34 @@ class BaseSpatialFeatures(object):
|
|||
|
||||
# The following properties indicate if the database backend support
|
||||
# certain lookups (dwithin, left and right, relate, ...)
|
||||
supports_distances_lookups = True
|
||||
supports_left_right_lookups = False
|
||||
|
||||
@property
|
||||
def supports_relate_lookup(self):
|
||||
return 'relate' in self.connection.ops.geometry_functions
|
||||
def supports_bbcontains_lookup(self):
|
||||
return 'bbcontains' in self.connection.ops.gis_terms
|
||||
|
||||
@property
|
||||
def has_dwithin_lookup(self):
|
||||
def supports_contained_lookup(self):
|
||||
return 'contained' in self.connection.ops.gis_terms
|
||||
|
||||
@property
|
||||
def supports_dwithin_lookup(self):
|
||||
return 'dwithin' in self.connection.ops.distance_functions
|
||||
|
||||
@property
|
||||
def supports_relate_lookup(self):
|
||||
return 'relate' in self.connection.ops.gis_terms
|
||||
|
||||
# For each of those methods, the class will have a property named
|
||||
# `has_<name>_method` (defined in __init__) which accesses connection.ops
|
||||
# to determine GIS method availability.
|
||||
geoqueryset_methods = (
|
||||
'centroid', 'difference', 'envelope', 'force_rhr', 'geohash', 'gml',
|
||||
'intersection', 'kml', 'num_geom', 'perimeter', 'point_on_surface',
|
||||
'reverse', 'scale', 'snap_to_grid', 'svg', 'sym_difference',
|
||||
'transform', 'translate', 'union', 'unionagg',
|
||||
'area', 'centroid', 'difference', 'distance', 'distance_spheroid',
|
||||
'envelope', 'force_rhr', 'geohash', 'gml', 'intersection', 'kml',
|
||||
'length', 'num_geom', 'perimeter', 'point_on_surface', 'reverse',
|
||||
'scale', 'snap_to_grid', 'svg', 'sym_difference', 'transform',
|
||||
'translate', 'union', 'unionagg',
|
||||
)
|
||||
|
||||
# Specifies whether the Collect and Extent aggregates are supported by the database
|
||||
|
|
|
@ -10,6 +10,7 @@ from django.contrib.gis.db.backends.mysql.operations import MySQLOperations
|
|||
|
||||
class DatabaseFeatures(BaseSpatialFeatures, MySQLDatabaseFeatures):
|
||||
has_spatialrefsys_table = False
|
||||
supports_distances_lookups = False
|
||||
supports_transform = False
|
||||
supports_real_shape_operations = False
|
||||
supports_null_geometries = False
|
||||
|
|
|
@ -11,6 +11,7 @@ from django.contrib.gis.db.backends.postgis.schema import PostGISSchemaEditor
|
|||
|
||||
|
||||
class DatabaseFeatures(BaseSpatialFeatures, Psycopg2DatabaseFeatures):
|
||||
supports_3d_functions = True
|
||||
supports_left_right_lookups = True
|
||||
|
||||
|
||||
|
|
|
@ -631,8 +631,8 @@ class GeoQuerySet(QuerySet):
|
|||
u, unit_name, s = get_srid_info(self.query.transformed_srid, connection)
|
||||
geodetic = unit_name.lower() in geo_field.geodetic_units
|
||||
|
||||
if backend.spatialite and geodetic:
|
||||
raise ValueError('SQLite does not support linear distance calculations on geodetic coordinate systems.')
|
||||
if geodetic and not connection.features.supports_distance_geodetic:
|
||||
raise ValueError('This database does not support linear distance calculations on geodetic coordinate systems.')
|
||||
|
||||
if distance:
|
||||
if self.query.transformed_srid:
|
||||
|
@ -690,8 +690,8 @@ class GeoQuerySet(QuerySet):
|
|||
# works on 3D geometries.
|
||||
procedure_fmt += ",'%(spheroid)s'"
|
||||
procedure_args.update({'function': backend.length_spheroid, 'spheroid': params[1]})
|
||||
elif geom_3d and backend.postgis:
|
||||
# Use 3D variants of perimeter and length routines on PostGIS.
|
||||
elif geom_3d and connection.features.supports_3d_functions:
|
||||
# Use 3D variants of perimeter and length routines on supported backends.
|
||||
if perimeter:
|
||||
procedure_args.update({'function': backend.perimeter3d})
|
||||
elif length:
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
from django.contrib.gis.db import models
|
||||
from django.contrib.gis.tests.utils import gisfield_may_be_null
|
||||
from django.utils.encoding import python_2_unicode_compatible
|
||||
|
||||
|
||||
|
@ -38,7 +39,7 @@ class CensusZipcode(NamedModel):
|
|||
|
||||
class SouthTexasZipcode(NamedModel):
|
||||
"Model for a few South Texas ZIP codes."
|
||||
poly = models.PolygonField(srid=32140, null=True)
|
||||
poly = models.PolygonField(srid=32140, null=gisfield_may_be_null)
|
||||
|
||||
|
||||
class Interstate(NamedModel):
|
||||
|
|
|
@ -6,9 +6,7 @@ from django.db import connection
|
|||
from django.db.models import Q
|
||||
from django.contrib.gis.geos import HAS_GEOS
|
||||
from django.contrib.gis.measure import D # alias for Distance
|
||||
from django.contrib.gis.tests.utils import (
|
||||
mysql, oracle, postgis, spatialite, no_oracle
|
||||
)
|
||||
from django.contrib.gis.tests.utils import oracle, postgis, spatialite, no_oracle
|
||||
from django.test import TestCase, skipUnlessDBFeature
|
||||
|
||||
if HAS_GEOS:
|
||||
|
@ -18,8 +16,6 @@ if HAS_GEOS:
|
|||
SouthTexasCity, SouthTexasCityFt, CensusZipcode, SouthTexasZipcode)
|
||||
|
||||
|
||||
@skipUnless(HAS_GEOS and not mysql,
|
||||
"GEOS and spatial db (not mysql) are required.")
|
||||
@skipUnlessDBFeature("gis_enabled")
|
||||
class DistanceTest(TestCase):
|
||||
fixtures = ['initial']
|
||||
|
@ -50,7 +46,7 @@ class DistanceTest(TestCase):
|
|||
self.assertEqual(1, Interstate.objects.count())
|
||||
self.assertEqual(1, SouthTexasInterstate.objects.count())
|
||||
|
||||
@skipUnlessDBFeature("has_dwithin_lookup")
|
||||
@skipUnlessDBFeature("supports_dwithin_lookup")
|
||||
def test_dwithin(self):
|
||||
"""
|
||||
Test the `dwithin` lookup type.
|
||||
|
@ -99,6 +95,7 @@ class DistanceTest(TestCase):
|
|||
else:
|
||||
self.assertListEqual(au_cities, self.get_names(qs.filter(point__dwithin=(self.au_pnt, dist))))
|
||||
|
||||
@skipUnlessDBFeature("has_distance_method")
|
||||
def test_distance_projected(self):
|
||||
"""
|
||||
Test the `distance` GeoQuerySet method on projected coordinate systems.
|
||||
|
@ -139,7 +136,7 @@ class DistanceTest(TestCase):
|
|||
self.assertAlmostEqual(m_distances[i], c.distance.m, tol)
|
||||
self.assertAlmostEqual(ft_distances[i], c.distance.survey_ft, tol)
|
||||
|
||||
@skipUnlessDBFeature("supports_distance_geodetic")
|
||||
@skipUnlessDBFeature("has_distance_method", "supports_distance_geodetic")
|
||||
def test_distance_geodetic(self):
|
||||
"""
|
||||
Test the `distance` GeoQuerySet method on geodetic coordinate systems.
|
||||
|
@ -149,16 +146,16 @@ class DistanceTest(TestCase):
|
|||
# Testing geodetic distance calculation with a non-point geometry
|
||||
# (a LineString of Wollongong and Shellharbour coords).
|
||||
ls = LineString(((150.902, -34.4245), (150.87, -34.5789)))
|
||||
if oracle or postgis:
|
||||
# Reference query:
|
||||
# SELECT ST_distance_sphere(point, ST_GeomFromText('LINESTRING(150.9020 -34.4245,150.8700 -34.5789)', 4326)) FROM distapp_australiacity ORDER BY name;
|
||||
distances = [1120954.92533513, 140575.720018241, 640396.662906304,
|
||||
60580.9693849269, 972807.955955075, 568451.8357838,
|
||||
40435.4335201384, 0, 68272.3896586844, 12375.0643697706, 0]
|
||||
qs = AustraliaCity.objects.distance(ls).order_by('name')
|
||||
for city, distance in zip(qs, distances):
|
||||
# Testing equivalence to within a meter.
|
||||
self.assertAlmostEqual(distance, city.distance.m, 0)
|
||||
|
||||
# Reference query:
|
||||
# SELECT ST_distance_sphere(point, ST_GeomFromText('LINESTRING(150.9020 -34.4245,150.8700 -34.5789)', 4326)) FROM distapp_australiacity ORDER BY name;
|
||||
distances = [1120954.92533513, 140575.720018241, 640396.662906304,
|
||||
60580.9693849269, 972807.955955075, 568451.8357838,
|
||||
40435.4335201384, 0, 68272.3896586844, 12375.0643697706, 0]
|
||||
qs = AustraliaCity.objects.distance(ls).order_by('name')
|
||||
for city, distance in zip(qs, distances):
|
||||
# Testing equivalence to within a meter.
|
||||
self.assertAlmostEqual(distance, city.distance.m, 0)
|
||||
|
||||
# Got the reference distances using the raw SQL statements:
|
||||
# SELECT ST_distance_spheroid(point, ST_GeomFromText('POINT(151.231341 -33.952685)', 4326), 'SPHEROID["WGS 84",6378137.0,298.257223563]') FROM distapp_australiacity WHERE (NOT (id = 11));
|
||||
|
@ -197,6 +194,7 @@ class DistanceTest(TestCase):
|
|||
self.assertAlmostEqual(sphere_distances[i], c.distance.m, tol)
|
||||
|
||||
@no_oracle # Oracle already handles geographic distance calculation.
|
||||
@skipUnlessDBFeature("has_distance_method")
|
||||
def test_distance_transform(self):
|
||||
"""
|
||||
Test the `distance` GeoQuerySet method used with `transform` on a geographic field.
|
||||
|
@ -226,6 +224,7 @@ class DistanceTest(TestCase):
|
|||
for i, z in enumerate(qs):
|
||||
self.assertAlmostEqual(z.distance.m, dists_m[i], 5)
|
||||
|
||||
@skipUnlessDBFeature("supports_distances_lookups")
|
||||
def test_distance_lookups(self):
|
||||
"""
|
||||
Test the `distance_lt`, `distance_gt`, `distance_lte`, and `distance_gte` lookup types.
|
||||
|
@ -255,6 +254,7 @@ class DistanceTest(TestCase):
|
|||
qs = SouthTexasZipcode.objects.exclude(name='77005').filter(poly__distance_lte=(z.poly, D(m=300)))
|
||||
self.assertEqual(['77002', '77025', '77401'], self.get_names(qs))
|
||||
|
||||
@skipUnlessDBFeature("supports_distances_lookups", "supports_distance_geodetic")
|
||||
def test_geodetic_distance_lookups(self):
|
||||
"""
|
||||
Test distance lookups on geodetic coordinate systems.
|
||||
|
@ -264,23 +264,11 @@ class DistanceTest(TestCase):
|
|||
line = GEOSGeometry('LINESTRING(144.9630 -37.8143,151.2607 -33.8870)', 4326)
|
||||
dist_qs = AustraliaCity.objects.filter(point__distance_lte=(line, D(km=100)))
|
||||
|
||||
if oracle or postgis:
|
||||
# Oracle and PostGIS can do distance lookups on arbitrary geometries.
|
||||
self.assertEqual(9, dist_qs.count())
|
||||
self.assertEqual(['Batemans Bay', 'Canberra', 'Hillsdale',
|
||||
'Melbourne', 'Mittagong', 'Shellharbour',
|
||||
'Sydney', 'Thirroul', 'Wollongong'],
|
||||
self.get_names(dist_qs))
|
||||
else:
|
||||
# spatialite only allow geodetic distance queries (utilizing
|
||||
# ST_Distance_Sphere/ST_Distance_Spheroid) from Points to PointFields
|
||||
# on geometry columns.
|
||||
self.assertRaises(ValueError, dist_qs.count)
|
||||
|
||||
# Ensured that a ValueError was raised, none of the rest of the test is
|
||||
# support on this backend, so bail now.
|
||||
if spatialite:
|
||||
return
|
||||
self.assertEqual(9, dist_qs.count())
|
||||
self.assertEqual(['Batemans Bay', 'Canberra', 'Hillsdale',
|
||||
'Melbourne', 'Mittagong', 'Shellharbour',
|
||||
'Sydney', 'Thirroul', 'Wollongong'],
|
||||
self.get_names(dist_qs))
|
||||
|
||||
# Too many params (4 in this case) should raise a ValueError.
|
||||
self.assertRaises(ValueError, len,
|
||||
|
@ -309,18 +297,18 @@ class DistanceTest(TestCase):
|
|||
# Geodetic distance lookup but telling GeoDjango to use `distance_spheroid`
|
||||
# instead (we should get the same results b/c accuracy variance won't matter
|
||||
# in this test case).
|
||||
if postgis:
|
||||
querysets = [qs1]
|
||||
if connection.features.has_distance_spheroid_method:
|
||||
gq3 = Q(point__distance_lte=(wollongong.point, d1, 'spheroid'))
|
||||
gq4 = Q(point__distance_gte=(wollongong.point, d2, 'spheroid'))
|
||||
qs2 = AustraliaCity.objects.exclude(name='Wollongong').filter(gq3 | gq4)
|
||||
querysets = [qs1, qs2]
|
||||
else:
|
||||
querysets = [qs1]
|
||||
querysets.append(qs2)
|
||||
|
||||
for qs in querysets:
|
||||
cities = self.get_names(qs)
|
||||
self.assertEqual(cities, ['Adelaide', 'Hobart', 'Shellharbour', 'Thirroul'])
|
||||
|
||||
@skipUnlessDBFeature("has_area_method")
|
||||
def test_area(self):
|
||||
"""
|
||||
Test the `area` GeoQuerySet method.
|
||||
|
@ -333,6 +321,7 @@ class DistanceTest(TestCase):
|
|||
for i, z in enumerate(SouthTexasZipcode.objects.order_by('name').area()):
|
||||
self.assertAlmostEqual(area_sq_m[i], z.area.sq_m, tol)
|
||||
|
||||
@skipUnlessDBFeature("has_length_method")
|
||||
def test_length(self):
|
||||
"""
|
||||
Test the `length` GeoQuerySet method.
|
||||
|
@ -342,13 +331,13 @@ class DistanceTest(TestCase):
|
|||
len_m1 = 473504.769553813
|
||||
len_m2 = 4617.668
|
||||
|
||||
if spatialite:
|
||||
# Does not support geodetic coordinate systems.
|
||||
self.assertRaises(ValueError, Interstate.objects.length)
|
||||
else:
|
||||
if connection.features.supports_distance_geodetic:
|
||||
qs = Interstate.objects.length()
|
||||
tol = 2 if oracle else 3
|
||||
self.assertAlmostEqual(len_m1, qs[0].length.m, tol)
|
||||
else:
|
||||
# Does not support geodetic coordinate systems.
|
||||
self.assertRaises(ValueError, Interstate.objects.length)
|
||||
|
||||
# Now doing length on a projected coordinate system.
|
||||
i10 = SouthTexasInterstate.objects.length().get(name='I-10')
|
||||
|
@ -370,6 +359,7 @@ class DistanceTest(TestCase):
|
|||
for i, c in enumerate(SouthTexasCity.objects.perimeter(model_att='perim')):
|
||||
self.assertEqual(0, c.perim.m)
|
||||
|
||||
@skipUnlessDBFeature("has_area_method", "has_distance_method")
|
||||
def test_measurement_null_fields(self):
|
||||
"""
|
||||
Test the measurement GeoQuerySet methods on fields with NULL values.
|
||||
|
|
|
@ -6,8 +6,7 @@ from unittest import skipUnless
|
|||
|
||||
from django.contrib.gis.gdal import HAS_GDAL
|
||||
from django.contrib.gis.geos import HAS_GEOS
|
||||
from django.contrib.gis.tests.utils import postgis
|
||||
from django.test import TestCase
|
||||
from django.test import TestCase, skipUnlessDBFeature
|
||||
from django.utils._os import upath
|
||||
|
||||
if HAS_GEOS:
|
||||
|
@ -62,7 +61,8 @@ bbox_data = (
|
|||
)
|
||||
|
||||
|
||||
@skipUnless(HAS_GEOS and HAS_GDAL and postgis, "Geos, GDAL and postgis are required.")
|
||||
@skipUnless(HAS_GDAL, "GDAL is required for Geo3DTest.")
|
||||
@skipUnlessDBFeature("gis_enabled", "supports_3d_functions")
|
||||
class Geo3DTest(TestCase):
|
||||
"""
|
||||
Only a subset of the PostGIS routines are 3D-enabled, and this TestCase
|
||||
|
@ -70,7 +70,7 @@ class Geo3DTest(TestCase):
|
|||
available within GeoDjango. For more information, see the PostGIS docs
|
||||
on the routines that support 3D:
|
||||
|
||||
http://postgis.refractions.net/documentation/manual-1.5/ch08.html#PostGIS_3D_Functions
|
||||
http://postgis.net/docs/PostGIS_Special_Functions_Index.html#PostGIS_3D_Functions
|
||||
"""
|
||||
|
||||
def _load_interstate_data(self):
|
||||
|
|
|
@ -1,10 +1,7 @@
|
|||
from django.contrib.gis.db import models
|
||||
from django.contrib.gis.tests.utils import mysql
|
||||
from django.contrib.gis.tests.utils import gisfield_may_be_null
|
||||
from django.utils.encoding import python_2_unicode_compatible
|
||||
|
||||
# MySQL spatial indices can't handle NULL geometries.
|
||||
null_flag = not mysql
|
||||
|
||||
|
||||
@python_2_unicode_compatible
|
||||
class NamedModel(models.Model):
|
||||
|
@ -42,7 +39,7 @@ class PennsylvaniaCity(City):
|
|||
|
||||
|
||||
class State(NamedModel):
|
||||
poly = models.PolygonField(null=null_flag) # Allowing NULL geometries here.
|
||||
poly = models.PolygonField(null=gisfield_may_be_null) # Allowing NULL geometries here.
|
||||
|
||||
|
||||
class Track(NamedModel):
|
||||
|
|
|
@ -2,12 +2,11 @@ from __future__ import unicode_literals
|
|||
|
||||
import re
|
||||
import unittest
|
||||
from unittest import skipUnless
|
||||
|
||||
from django.db import connection
|
||||
from django.contrib.gis import gdal
|
||||
from django.contrib.gis.geos import HAS_GEOS
|
||||
from django.contrib.gis.tests.utils import mysql, oracle, postgis, spatialite
|
||||
from django.contrib.gis.tests.utils import oracle, postgis, spatialite
|
||||
from django.test import TestCase, skipUnlessDBFeature
|
||||
from django.utils import six
|
||||
|
||||
|
@ -142,11 +141,12 @@ class GeoModelTest(TestCase):
|
|||
|
||||
# If the GeometryField SRID is -1, then we shouldn't perform any
|
||||
# transformation if the SRID of the input geometry is different.
|
||||
# SpatiaLite does not support missing SRID values.
|
||||
if not spatialite:
|
||||
m1 = MinusOneSRID(geom=Point(17, 23, srid=4326))
|
||||
m1.save()
|
||||
self.assertEqual(-1, m1.geom.srid)
|
||||
if spatialite and connection.ops.spatial_version < 3:
|
||||
# SpatiaLite < 3 does not support missing SRID values.
|
||||
return
|
||||
m1 = MinusOneSRID(geom=Point(17, 23, srid=4326))
|
||||
m1.save()
|
||||
self.assertEqual(-1, m1.geom.srid)
|
||||
|
||||
def test_createnull(self):
|
||||
"Testing creating a model instance and the geometry being None"
|
||||
|
@ -223,7 +223,7 @@ class GeoLookupTest(TestCase):
|
|||
# Seeing what cities are in Texas, should get Houston and Dallas,
|
||||
# and Oklahoma City because 'contained' only checks on the
|
||||
# _bounding box_ of the Geometries.
|
||||
if not oracle:
|
||||
if connection.features.supports_contained_lookup:
|
||||
qs = City.objects.filter(point__contained=texas.mpoly)
|
||||
self.assertEqual(3, qs.count())
|
||||
cities = ['Houston', 'Dallas', 'Oklahoma City']
|
||||
|
@ -245,23 +245,22 @@ class GeoLookupTest(TestCase):
|
|||
self.assertEqual('New Zealand', nz.name)
|
||||
|
||||
# Spatialite 2.3 thinks that Lawrence is in Puerto Rico (a NULL geometry).
|
||||
if not spatialite:
|
||||
if not (spatialite and connection.ops.spatial_version < 3):
|
||||
ks = State.objects.get(poly__contains=lawrence.point)
|
||||
self.assertEqual('Kansas', ks.name)
|
||||
|
||||
# Pueblo and Oklahoma City (even though OK City is within the bounding box of Texas)
|
||||
# are not contained in Texas or New Zealand.
|
||||
self.assertEqual(0, len(Country.objects.filter(mpoly__contains=pueblo.point))) # Query w/GEOSGeometry object
|
||||
self.assertEqual((mysql and 1) or 0,
|
||||
len(Country.objects.filter(mpoly__contains=okcity.point.wkt))) # Qeury w/WKT
|
||||
self.assertEqual(len(Country.objects.filter(mpoly__contains=pueblo.point)), 0) # Query w/GEOSGeometry object
|
||||
self.assertEqual(len(Country.objects.filter(mpoly__contains=okcity.point.wkt)),
|
||||
0 if connection.features.supports_real_shape_operations else 1) # Query w/WKT
|
||||
|
||||
# OK City is contained w/in bounding box of Texas.
|
||||
if not oracle:
|
||||
if connection.features.supports_bbcontains_lookup:
|
||||
qs = Country.objects.filter(mpoly__bbcontains=okcity.point)
|
||||
self.assertEqual(1, len(qs))
|
||||
self.assertEqual('Texas', qs[0].name)
|
||||
|
||||
# Only PostGIS has `left` and `right` lookup types.
|
||||
@skipUnlessDBFeature("supports_left_right_lookups")
|
||||
def test_left_right_lookups(self):
|
||||
"Testing the 'left' and 'right' lookup types."
|
||||
|
@ -409,10 +408,9 @@ class GeoQuerySetTest(TestCase):
|
|||
for s in qs:
|
||||
self.assertEqual(True, s.poly.centroid.equals_exact(s.centroid, tol))
|
||||
|
||||
@skipUnlessDBFeature("has_difference_method")
|
||||
@skipUnlessDBFeature("has_intersection_method")
|
||||
@skipUnlessDBFeature("has_sym_difference_method")
|
||||
@skipUnlessDBFeature("has_union_method")
|
||||
@skipUnlessDBFeature(
|
||||
"has_difference_method", "has_intersection_method",
|
||||
"has_sym_difference_method", "has_union_method")
|
||||
def test_diff_intersection_union(self):
|
||||
"Testing the `difference`, `intersection`, `sym_difference`, and `union` GeoQuerySet methods."
|
||||
geom = Point(5, 23)
|
||||
|
@ -610,7 +608,7 @@ class GeoQuerySetTest(TestCase):
|
|||
'Texas': fromstr('POINT (-103.002434 36.500397)', srid=4326),
|
||||
}
|
||||
|
||||
elif postgis or spatialite:
|
||||
else:
|
||||
# Using GEOSGeometry to compute the reference point on surface values
|
||||
# -- since PostGIS also uses GEOS these should be the same.
|
||||
ref = {'New Zealand': Country.objects.get(name='New Zealand').mpoly.point_on_surface,
|
||||
|
|
|
@ -10,14 +10,14 @@ from django.contrib.gis.gdal import HAS_GDAL
|
|||
from django.contrib.gis.geos import HAS_GEOS
|
||||
from django.contrib.gis.measure import D
|
||||
from django.contrib.gis.tests.utils import postgis
|
||||
from django.test import TestCase
|
||||
from django.test import TestCase, skipUnlessDBFeature
|
||||
from django.utils._os import upath
|
||||
|
||||
if HAS_GEOS:
|
||||
from .models import City, County, Zipcode
|
||||
|
||||
|
||||
@skipUnless(HAS_GEOS and postgis, "Geos and postgis are required.")
|
||||
@skipUnlessDBFeature("gis_enabled")
|
||||
class GeographyTest(TestCase):
|
||||
fixtures = ['initial']
|
||||
|
||||
|
@ -25,6 +25,7 @@ class GeographyTest(TestCase):
|
|||
"Ensure geography features loaded properly."
|
||||
self.assertEqual(8, City.objects.count())
|
||||
|
||||
@skipUnlessDBFeature("supports_distances_lookups", "supports_distance_geodetic")
|
||||
def test02_distance_lookup(self):
|
||||
"Testing GeoQuerySet distance lookup support on non-point geography fields."
|
||||
z = Zipcode.objects.get(code='77002')
|
||||
|
@ -39,12 +40,14 @@ class GeographyTest(TestCase):
|
|||
for cities in [cities1, cities2]:
|
||||
self.assertEqual(['Dallas', 'Houston', 'Oklahoma City'], cities)
|
||||
|
||||
@skipUnlessDBFeature("has_distance_method", "supports_distance_geodetic")
|
||||
def test03_distance_method(self):
|
||||
"Testing GeoQuerySet.distance() support on non-point geography fields."
|
||||
# `GeoQuerySet.distance` is not allowed geometry fields.
|
||||
htown = City.objects.get(name='Houston')
|
||||
Zipcode.objects.distance(htown.point)
|
||||
|
||||
@skipUnless(postgis, "This is a PostGIS-specific test")
|
||||
def test04_invalid_operators_functions(self):
|
||||
"Ensuring exceptions are raised for operators & functions invalid on geography fields."
|
||||
# Only a subset of the geometry functions & operator are available
|
||||
|
@ -89,6 +92,7 @@ class GeographyTest(TestCase):
|
|||
self.assertEqual(name, c.name)
|
||||
self.assertEqual(state, c.state)
|
||||
|
||||
@skipUnlessDBFeature("has_area_method", "supports_distance_geodetic")
|
||||
def test06_geography_area(self):
|
||||
"Testing that Area calculations work on geography columns."
|
||||
# SELECT ST_Area(poly) FROM geogapp_zipcode WHERE code='77002';
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
from __future__ import unicode_literals
|
||||
|
||||
import os
|
||||
import re
|
||||
from unittest import skipUnless
|
||||
|
||||
from django.core.management import call_command
|
||||
|
@ -11,7 +12,7 @@ from django.contrib.gis.geometry.test_data import TEST_DATA
|
|||
from django.utils.six import StringIO
|
||||
|
||||
if HAS_GDAL:
|
||||
from django.contrib.gis.gdal import Driver
|
||||
from django.contrib.gis.gdal import Driver, OGRException
|
||||
from django.contrib.gis.utils.ogrinspect import ogrinspect
|
||||
|
||||
from .models import AllOGRFields
|
||||
|
@ -77,23 +78,20 @@ class OGRInspectTest(TestCase):
|
|||
self.assertEqual(model_def, '\n'.join(expected))
|
||||
|
||||
def test_time_field(self):
|
||||
# Only possible to test this on PostGIS at the moment. MySQL
|
||||
# complains about permissions, and SpatiaLite/Oracle are
|
||||
# insanely difficult to get support compiled in for in GDAL.
|
||||
if not connections['default'].ops.postgis:
|
||||
self.skipTest("This database does not support 'ogrinspect'ion")
|
||||
|
||||
# Getting the database identifier used by OGR, if None returned
|
||||
# GDAL does not have the support compiled in.
|
||||
ogr_db = get_ogr_db_string()
|
||||
if not ogr_db:
|
||||
self.skipTest("Your GDAL installation does not support PostGIS databases")
|
||||
self.skipTest("Unable to setup an OGR connection to your database")
|
||||
|
||||
# Writing shapefiles via GDAL currently does not support writing OGRTime
|
||||
# fields, so we need to actually use a database
|
||||
model_def = ogrinspect(ogr_db, 'Measurement',
|
||||
layer_key=AllOGRFields._meta.db_table,
|
||||
decimal=['f_decimal'])
|
||||
try:
|
||||
# Writing shapefiles via GDAL currently does not support writing OGRTime
|
||||
# fields, so we need to actually use a database
|
||||
model_def = ogrinspect(ogr_db, 'Measurement',
|
||||
layer_key=AllOGRFields._meta.db_table,
|
||||
decimal=['f_decimal'])
|
||||
except OGRException:
|
||||
self.skipTest("Unable to setup an OGR connection to your database")
|
||||
|
||||
self.assertTrue(model_def.startswith(
|
||||
'# This is an auto-generated Django model module created by ogrinspect.\n'
|
||||
|
@ -111,10 +109,9 @@ class OGRInspectTest(TestCase):
|
|||
self.assertIn(' f_char = models.CharField(max_length=10)', model_def)
|
||||
self.assertIn(' f_date = models.DateField()', model_def)
|
||||
|
||||
self.assertTrue(model_def.endswith(
|
||||
' geom = models.PolygonField()\n'
|
||||
' objects = models.GeoManager()'
|
||||
))
|
||||
self.assertIsNotNone(re.search(
|
||||
r' geom = models.PolygonField\(([^\)])*\)\n' # Some backends may have srid=-1
|
||||
r' objects = models.GeoManager\(\)', model_def))
|
||||
|
||||
def test_management_command(self):
|
||||
shp_file = os.path.join(TEST_DATA, 'cities', 'cities.shp')
|
||||
|
@ -142,7 +139,7 @@ def get_ogr_db_string():
|
|||
'django.contrib.gis.db.backends.spatialite': ('SQLite', '%(db_name)s', '')
|
||||
}
|
||||
|
||||
drv_name, db_str, param_sep = drivers[db['ENGINE']]
|
||||
drv_name, db_str, param_sep = drivers.get(db['ENGINE'])
|
||||
|
||||
# Ensure that GDAL library has driver support for the database.
|
||||
try:
|
||||
|
|
|
@ -8,8 +8,7 @@ import unittest
|
|||
from unittest import skipUnless
|
||||
|
||||
from django.contrib.gis.gdal import HAS_GDAL
|
||||
from django.contrib.gis.tests.utils import mysql
|
||||
from django.db import router
|
||||
from django.db import connection, router
|
||||
from django.conf import settings
|
||||
from django.test import TestCase, skipUnlessDBFeature
|
||||
from django.utils._os import upath
|
||||
|
@ -151,7 +150,7 @@ class LayerMapTest(TestCase):
|
|||
# Unique may take tuple or string parameters.
|
||||
for arg in ('name', ('name', 'mpoly')):
|
||||
lm = LayerMapping(County, co_shp, co_mapping, transform=False, unique=arg)
|
||||
except:
|
||||
except Exception:
|
||||
self.fail('No exception should be raised for proper use of keywords.')
|
||||
|
||||
# Testing invalid params for the `unique` keyword.
|
||||
|
@ -159,7 +158,7 @@ class LayerMapTest(TestCase):
|
|||
self.assertRaises(e, LayerMapping, County, co_shp, co_mapping, transform=False, unique=arg)
|
||||
|
||||
# No source reference system defined in the shapefile, should raise an error.
|
||||
if not mysql:
|
||||
if connection.features.supports_transform:
|
||||
self.assertRaises(LayerMapError, LayerMapping, County, co_shp, co_mapping)
|
||||
|
||||
# Passing in invalid ForeignKey mapping parameters -- must be a dictionary
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
from __future__ import unicode_literals
|
||||
|
||||
from django.contrib.gis.geos import HAS_GEOS
|
||||
from django.contrib.gis.tests.utils import mysql, no_oracle
|
||||
from django.contrib.gis.tests.utils import no_oracle
|
||||
from django.db import connection
|
||||
from django.test import TestCase, skipUnlessDBFeature
|
||||
|
||||
if HAS_GEOS:
|
||||
|
@ -146,7 +147,7 @@ class RelatedGeoModelTest(TestCase):
|
|||
self.assertEqual(1, len(qs))
|
||||
self.assertEqual('P2', qs[0].name)
|
||||
|
||||
if not mysql:
|
||||
if connection.features.supports_transform:
|
||||
# This time center2 is in a different coordinate system and needs
|
||||
# to be wrapped in transformation SQL.
|
||||
qs = Parcel.objects.filter(center2__within=F('border1'))
|
||||
|
@ -159,7 +160,7 @@ class RelatedGeoModelTest(TestCase):
|
|||
self.assertEqual(1, len(qs))
|
||||
self.assertEqual('P1', qs[0].name)
|
||||
|
||||
if not mysql:
|
||||
if connection.features.supports_transform:
|
||||
# This time the city column should be wrapped in transformation SQL.
|
||||
qs = Parcel.objects.filter(border2__contains=F('city__location__point'))
|
||||
self.assertEqual(1, len(qs))
|
||||
|
|
|
@ -28,6 +28,9 @@ postgis = _default_db == 'postgis'
|
|||
mysql = _default_db == 'mysql'
|
||||
spatialite = _default_db == 'spatialite'
|
||||
|
||||
# MySQL spatial indices can't handle NULL geometries.
|
||||
gisfield_may_be_null = not mysql
|
||||
|
||||
if oracle and 'gis' in settings.DATABASES[DEFAULT_DB_ALIAS]['ENGINE']:
|
||||
from django.contrib.gis.db.backends.oracle.models import OracleSpatialRefSys as SpatialRefSys
|
||||
elif postgis:
|
||||
|
|
|
@ -103,10 +103,10 @@ class LayerMapping(object):
|
|||
|
||||
# Getting the geometry column associated with the model (an
|
||||
# exception will be raised if there is no geometry column).
|
||||
if self.spatial_backend.mysql:
|
||||
transform = False
|
||||
else:
|
||||
if connections[self.using].features.supports_transform:
|
||||
self.geo_field = self.geometry_field()
|
||||
else:
|
||||
transform = False
|
||||
|
||||
# Checking the source spatial reference system, and getting
|
||||
# the coordinate transformation object (unless the `transform`
|
||||
|
|
Loading…
Reference in New Issue