Replaced no_spatialite by connection features
Refs #22632. Thanks Tim Graham for the review.
This commit is contained in:
parent
46c7707e50
commit
a7d964ab87
|
@ -11,8 +11,56 @@ from django.utils.encoding import python_2_unicode_compatible
|
||||||
|
|
||||||
class BaseSpatialFeatures(object):
|
class BaseSpatialFeatures(object):
|
||||||
gis_enabled = True
|
gis_enabled = True
|
||||||
|
|
||||||
|
# Does the database contain a SpatialRefSys model to store SRID information?
|
||||||
has_spatialrefsys_table = True
|
has_spatialrefsys_table = True
|
||||||
|
|
||||||
|
# Can the `distance` GeoQuerySet method be applied on geodetic coordinate systems?
|
||||||
|
supports_distance_geodetic = True
|
||||||
|
# Does the database supports `left` and `right` lookups?
|
||||||
|
supports_left_right_lookups = False
|
||||||
|
# Is the database able to count vertices on polygons (with `num_points`)?
|
||||||
|
supports_num_points_poly = True
|
||||||
|
|
||||||
|
# The following properties indicate if the database GIS extensions support
|
||||||
|
# certain methods (dwithin, force_rhr, geohash, ...)
|
||||||
|
@property
|
||||||
|
def has_dwithin_lookup(self):
|
||||||
|
return 'dwithin' in self.connection.ops.distance_functions
|
||||||
|
|
||||||
|
@property
|
||||||
|
def has_force_rhr_method(self):
|
||||||
|
return bool(self.connection.ops.force_rhr)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def has_geohash_method(self):
|
||||||
|
return bool(self.connection.ops.geohash)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def has_make_line_method(self):
|
||||||
|
return bool(self.connection.ops.make_line)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def has_perimeter_method(self):
|
||||||
|
return bool(self.connection.ops.perimeter)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def has_reverse_method(self):
|
||||||
|
return bool(self.connection.ops.reverse)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def has_snap_to_grid_method(self):
|
||||||
|
return bool(self.connection.ops.snap_to_grid)
|
||||||
|
|
||||||
|
# Specifies whether the Collect and Extent aggregates are supported by the database
|
||||||
|
@property
|
||||||
|
def supports_collect_aggr(self):
|
||||||
|
return 'Collect' in self.connection.ops.valid_aggregates
|
||||||
|
|
||||||
|
@property
|
||||||
|
def supports_extent_aggr(self):
|
||||||
|
return 'Extent' in self.connection.ops.valid_aggregates
|
||||||
|
|
||||||
|
|
||||||
class BaseSpatialOperations(object):
|
class BaseSpatialOperations(object):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -10,6 +10,7 @@ from django.contrib.gis.db.backends.mysql.operations import MySQLOperations
|
||||||
|
|
||||||
class DatabaseFeatures(BaseSpatialFeatures, MySQLDatabaseFeatures):
|
class DatabaseFeatures(BaseSpatialFeatures, MySQLDatabaseFeatures):
|
||||||
has_spatialrefsys_table = False
|
has_spatialrefsys_table = False
|
||||||
|
supports_num_points_poly = False
|
||||||
|
|
||||||
|
|
||||||
class DatabaseWrapper(MySQLDatabaseWrapper):
|
class DatabaseWrapper(MySQLDatabaseWrapper):
|
||||||
|
|
|
@ -11,7 +11,7 @@ from django.contrib.gis.db.backends.postgis.schema import PostGISSchemaEditor
|
||||||
|
|
||||||
|
|
||||||
class DatabaseFeatures(BaseSpatialFeatures, Psycopg2DatabaseFeatures):
|
class DatabaseFeatures(BaseSpatialFeatures, Psycopg2DatabaseFeatures):
|
||||||
pass
|
supports_left_right_lookups = True
|
||||||
|
|
||||||
|
|
||||||
class DatabaseWrapper(Psycopg2DatabaseWrapper):
|
class DatabaseWrapper(Psycopg2DatabaseWrapper):
|
||||||
|
|
|
@ -16,7 +16,9 @@ from django.utils import six
|
||||||
|
|
||||||
|
|
||||||
class DatabaseFeatures(BaseSpatialFeatures, SQLiteDatabaseFeatures):
|
class DatabaseFeatures(BaseSpatialFeatures, SQLiteDatabaseFeatures):
|
||||||
pass
|
supports_distance_geodetic = False
|
||||||
|
# SpatiaLite can only count vertices in LineStrings
|
||||||
|
supports_num_points_poly = False
|
||||||
|
|
||||||
|
|
||||||
class DatabaseWrapper(SQLiteDatabaseWrapper):
|
class DatabaseWrapper(SQLiteDatabaseWrapper):
|
||||||
|
|
|
@ -65,17 +65,25 @@ class SpatiaLiteOperations(DatabaseOperations, BaseSpatialOperations):
|
||||||
name = 'spatialite'
|
name = 'spatialite'
|
||||||
spatialite = True
|
spatialite = True
|
||||||
version_regex = re.compile(r'^(?P<major>\d)\.(?P<minor1>\d)\.(?P<minor2>\d+)')
|
version_regex = re.compile(r'^(?P<major>\d)\.(?P<minor1>\d)\.(?P<minor2>\d+)')
|
||||||
valid_aggregates = {'Extent', 'Union'}
|
|
||||||
|
@property
|
||||||
|
def valid_aggregates(self):
|
||||||
|
if self.spatial_version >= 3:
|
||||||
|
return {'Collect', 'Extent', 'Union'}
|
||||||
|
else:
|
||||||
|
return {'Union'}
|
||||||
|
|
||||||
Adapter = SpatiaLiteAdapter
|
Adapter = SpatiaLiteAdapter
|
||||||
Adaptor = Adapter # Backwards-compatibility alias.
|
Adaptor = Adapter # Backwards-compatibility alias.
|
||||||
|
|
||||||
area = 'Area'
|
area = 'Area'
|
||||||
centroid = 'Centroid'
|
centroid = 'Centroid'
|
||||||
|
collect = 'Collect'
|
||||||
contained = 'MbrWithin'
|
contained = 'MbrWithin'
|
||||||
difference = 'Difference'
|
difference = 'Difference'
|
||||||
distance = 'Distance'
|
distance = 'Distance'
|
||||||
envelope = 'Envelope'
|
envelope = 'Envelope'
|
||||||
|
extent = 'Extent'
|
||||||
intersection = 'Intersection'
|
intersection = 'Intersection'
|
||||||
length = 'GLength' # OpenGis defines Length, but this conflicts with an SQLite reserved keyword
|
length = 'GLength' # OpenGis defines Length, but this conflicts with an SQLite reserved keyword
|
||||||
num_geom = 'NumGeometries'
|
num_geom = 'NumGeometries'
|
||||||
|
@ -180,6 +188,15 @@ class SpatiaLiteOperations(DatabaseOperations, BaseSpatialOperations):
|
||||||
agg_name = aggregate.__class__.__name__
|
agg_name = aggregate.__class__.__name__
|
||||||
return agg_name in self.valid_aggregates
|
return agg_name in self.valid_aggregates
|
||||||
|
|
||||||
|
def convert_extent(self, box):
|
||||||
|
"""
|
||||||
|
Convert the polygon data received from Spatialite to min/max values.
|
||||||
|
"""
|
||||||
|
shell = Geometry(box).shell
|
||||||
|
xmin, ymin = shell[0][:2]
|
||||||
|
xmax, ymax = shell[2][:2]
|
||||||
|
return (xmin, ymin, xmax, ymax)
|
||||||
|
|
||||||
def convert_geom(self, wkt, geo_field):
|
def convert_geom(self, wkt, geo_field):
|
||||||
"""
|
"""
|
||||||
Converts geometry WKT returned from a SpatiaLite aggregate.
|
Converts geometry WKT returned from a SpatiaLite aggregate.
|
||||||
|
|
|
@ -7,7 +7,7 @@ from django.db.models import Q
|
||||||
from django.contrib.gis.geos import HAS_GEOS
|
from django.contrib.gis.geos import HAS_GEOS
|
||||||
from django.contrib.gis.measure import D # alias for Distance
|
from django.contrib.gis.measure import D # alias for Distance
|
||||||
from django.contrib.gis.tests.utils import (
|
from django.contrib.gis.tests.utils import (
|
||||||
mysql, oracle, postgis, spatialite, no_oracle, no_spatialite
|
mysql, oracle, postgis, spatialite, no_oracle
|
||||||
)
|
)
|
||||||
from django.test import TestCase, skipUnlessDBFeature
|
from django.test import TestCase, skipUnlessDBFeature
|
||||||
|
|
||||||
|
@ -50,7 +50,7 @@ class DistanceTest(TestCase):
|
||||||
self.assertEqual(1, Interstate.objects.count())
|
self.assertEqual(1, Interstate.objects.count())
|
||||||
self.assertEqual(1, SouthTexasInterstate.objects.count())
|
self.assertEqual(1, SouthTexasInterstate.objects.count())
|
||||||
|
|
||||||
@no_spatialite
|
@skipUnlessDBFeature("has_dwithin_lookup")
|
||||||
def test_dwithin(self):
|
def test_dwithin(self):
|
||||||
"""
|
"""
|
||||||
Test the `dwithin` lookup type.
|
Test the `dwithin` lookup type.
|
||||||
|
@ -139,7 +139,7 @@ class DistanceTest(TestCase):
|
||||||
self.assertAlmostEqual(m_distances[i], c.distance.m, tol)
|
self.assertAlmostEqual(m_distances[i], c.distance.m, tol)
|
||||||
self.assertAlmostEqual(ft_distances[i], c.distance.survey_ft, tol)
|
self.assertAlmostEqual(ft_distances[i], c.distance.survey_ft, tol)
|
||||||
|
|
||||||
@no_spatialite
|
@skipUnlessDBFeature("supports_distance_geodetic")
|
||||||
def test_distance_geodetic(self):
|
def test_distance_geodetic(self):
|
||||||
"""
|
"""
|
||||||
Test the `distance` GeoQuerySet method on geodetic coordinate systems.
|
Test the `distance` GeoQuerySet method on geodetic coordinate systems.
|
||||||
|
@ -354,7 +354,7 @@ class DistanceTest(TestCase):
|
||||||
i10 = SouthTexasInterstate.objects.length().get(name='I-10')
|
i10 = SouthTexasInterstate.objects.length().get(name='I-10')
|
||||||
self.assertAlmostEqual(len_m2, i10.length.m, 2)
|
self.assertAlmostEqual(len_m2, i10.length.m, 2)
|
||||||
|
|
||||||
@no_spatialite
|
@skipUnlessDBFeature("has_perimeter_method")
|
||||||
def test_perimeter(self):
|
def test_perimeter(self):
|
||||||
"""
|
"""
|
||||||
Test the `perimeter` GeoQuerySet method.
|
Test the `perimeter` GeoQuerySet method.
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
from django.contrib.gis.db import models
|
from django.contrib.gis.db import models
|
||||||
from django.contrib.gis.tests.utils import mysql, spatialite
|
from django.contrib.gis.tests.utils import mysql
|
||||||
from django.utils.encoding import python_2_unicode_compatible
|
from django.utils.encoding import python_2_unicode_compatible
|
||||||
|
|
||||||
# MySQL spatial indices can't handle NULL geometries.
|
# MySQL spatial indices can't handle NULL geometries.
|
||||||
|
@ -58,15 +58,14 @@ class Truth(models.Model):
|
||||||
app_label = 'geoapp'
|
app_label = 'geoapp'
|
||||||
|
|
||||||
|
|
||||||
if not spatialite:
|
class Feature(NamedModel):
|
||||||
|
geom = models.GeometryField()
|
||||||
|
|
||||||
class Feature(NamedModel):
|
|
||||||
geom = models.GeometryField()
|
|
||||||
|
|
||||||
class MinusOneSRID(models.Model):
|
class MinusOneSRID(models.Model):
|
||||||
geom = models.PointField(srid=-1) # Minus one SRID.
|
geom = models.PointField(srid=-1) # Minus one SRID.
|
||||||
|
|
||||||
objects = models.GeoManager()
|
objects = models.GeoManager()
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
app_label = 'geoapp'
|
app_label = 'geoapp'
|
||||||
|
|
|
@ -4,7 +4,6 @@ from __future__ import unicode_literals
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
from django.contrib.gis.geos import HAS_GEOS
|
from django.contrib.gis.geos import HAS_GEOS
|
||||||
from django.contrib.gis.tests.utils import no_mysql, no_spatialite
|
|
||||||
from django.contrib.gis.shortcuts import render_to_kmz
|
from django.contrib.gis.shortcuts import render_to_kmz
|
||||||
from django.db.models import Count, Min
|
from django.db.models import Count, Min
|
||||||
from django.test import TestCase, skipUnlessDBFeature
|
from django.test import TestCase, skipUnlessDBFeature
|
||||||
|
@ -39,8 +38,7 @@ class GeoRegressionTests(TestCase):
|
||||||
}]
|
}]
|
||||||
render_to_kmz('gis/kml/placemarks.kml', {'places': places})
|
render_to_kmz('gis/kml/placemarks.kml', {'places': places})
|
||||||
|
|
||||||
@no_spatialite
|
@skipUnlessDBFeature("supports_extent_aggr")
|
||||||
@no_mysql
|
|
||||||
def test_extent(self):
|
def test_extent(self):
|
||||||
"Testing `extent` on a table with a single point. See #11827."
|
"Testing `extent` on a table with a single point. See #11827."
|
||||||
pnt = City.objects.get(name='Pueblo').point
|
pnt = City.objects.get(name='Pueblo').point
|
||||||
|
|
|
@ -8,7 +8,7 @@ from django.db import connection
|
||||||
from django.contrib.gis import gdal
|
from django.contrib.gis import gdal
|
||||||
from django.contrib.gis.geos import HAS_GEOS
|
from django.contrib.gis.geos import HAS_GEOS
|
||||||
from django.contrib.gis.tests.utils import (
|
from django.contrib.gis.tests.utils import (
|
||||||
no_mysql, no_oracle, no_spatialite, mysql, oracle, postgis, spatialite)
|
no_mysql, no_oracle, mysql, oracle, postgis, spatialite)
|
||||||
from django.test import TestCase, skipUnlessDBFeature
|
from django.test import TestCase, skipUnlessDBFeature
|
||||||
from django.utils import six
|
from django.utils import six
|
||||||
|
|
||||||
|
@ -17,8 +17,6 @@ if HAS_GEOS:
|
||||||
Point, LineString, LinearRing, Polygon, GeometryCollection)
|
Point, LineString, LinearRing, Polygon, GeometryCollection)
|
||||||
|
|
||||||
from .models import Country, City, PennsylvaniaCity, State, Track
|
from .models import Country, City, PennsylvaniaCity, State, Track
|
||||||
|
|
||||||
if HAS_GEOS and not spatialite:
|
|
||||||
from .models import Feature, MinusOneSRID
|
from .models import Feature, MinusOneSRID
|
||||||
|
|
||||||
|
|
||||||
|
@ -156,7 +154,6 @@ class GeoModelTest(TestCase):
|
||||||
c = City()
|
c = City()
|
||||||
self.assertEqual(c.point, None)
|
self.assertEqual(c.point, None)
|
||||||
|
|
||||||
@no_spatialite # SpatiaLite does not support abstract geometry columns
|
|
||||||
def test_geometryfield(self):
|
def test_geometryfield(self):
|
||||||
"Testing the general GeometryField."
|
"Testing the general GeometryField."
|
||||||
Feature(name='Point', geom=Point(1, 1)).save()
|
Feature(name='Point', geom=Point(1, 1)).save()
|
||||||
|
@ -266,9 +263,7 @@ class GeoLookupTest(TestCase):
|
||||||
self.assertEqual('Texas', qs[0].name)
|
self.assertEqual('Texas', qs[0].name)
|
||||||
|
|
||||||
# Only PostGIS has `left` and `right` lookup types.
|
# Only PostGIS has `left` and `right` lookup types.
|
||||||
@no_mysql
|
@skipUnlessDBFeature("supports_left_right_lookups")
|
||||||
@no_oracle
|
|
||||||
@no_spatialite
|
|
||||||
def test_left_right_lookups(self):
|
def test_left_right_lookups(self):
|
||||||
"Testing the 'left' and 'right' lookup types."
|
"Testing the 'left' and 'right' lookup types."
|
||||||
# Left: A << B => true if xmax(A) < xmin(B)
|
# Left: A << B => true if xmax(A) < xmin(B)
|
||||||
|
@ -451,8 +446,7 @@ class GeoQuerySetTest(TestCase):
|
||||||
for country in countries:
|
for country in countries:
|
||||||
self.assertIsInstance(country.envelope, Polygon)
|
self.assertIsInstance(country.envelope, Polygon)
|
||||||
|
|
||||||
@no_mysql
|
@skipUnlessDBFeature("supports_extent_aggr")
|
||||||
@no_spatialite # SpatiaLite does not have an Extent function
|
|
||||||
def test_extent(self):
|
def test_extent(self):
|
||||||
"Testing the `extent` GeoQuerySet method."
|
"Testing the `extent` GeoQuerySet method."
|
||||||
# Reference query:
|
# Reference query:
|
||||||
|
@ -466,9 +460,7 @@ class GeoQuerySetTest(TestCase):
|
||||||
for val, exp in zip(extent, expected):
|
for val, exp in zip(extent, expected):
|
||||||
self.assertAlmostEqual(exp, val, 4)
|
self.assertAlmostEqual(exp, val, 4)
|
||||||
|
|
||||||
@no_mysql
|
@skipUnlessDBFeature("has_force_rhr_method")
|
||||||
@no_oracle
|
|
||||||
@no_spatialite
|
|
||||||
def test_force_rhr(self):
|
def test_force_rhr(self):
|
||||||
"Testing GeoQuerySet.force_rhr()."
|
"Testing GeoQuerySet.force_rhr()."
|
||||||
rings = (
|
rings = (
|
||||||
|
@ -483,13 +475,9 @@ class GeoQuerySetTest(TestCase):
|
||||||
s = State.objects.force_rhr().get(name='Foo')
|
s = State.objects.force_rhr().get(name='Foo')
|
||||||
self.assertEqual(rhr_rings, s.force_rhr.coords)
|
self.assertEqual(rhr_rings, s.force_rhr.coords)
|
||||||
|
|
||||||
@no_mysql
|
@skipUnlessDBFeature("has_geohash_method")
|
||||||
@no_oracle
|
|
||||||
@no_spatialite
|
|
||||||
def test_geohash(self):
|
def test_geohash(self):
|
||||||
"Testing GeoQuerySet.geohash()."
|
"Testing GeoQuerySet.geohash()."
|
||||||
if not connection.ops.geohash:
|
|
||||||
return
|
|
||||||
# Reference query:
|
# Reference query:
|
||||||
# SELECT ST_GeoHash(point) FROM geoapp_city WHERE name='Houston';
|
# SELECT ST_GeoHash(point) FROM geoapp_city WHERE name='Houston';
|
||||||
# SELECT ST_GeoHash(point, 5) FROM geoapp_city WHERE name='Houston';
|
# SELECT ST_GeoHash(point, 5) FROM geoapp_city WHERE name='Houston';
|
||||||
|
@ -501,7 +489,7 @@ class GeoQuerySetTest(TestCase):
|
||||||
|
|
||||||
def test_geojson(self):
|
def test_geojson(self):
|
||||||
"Testing GeoJSON output from the database using GeoQuerySet.geojson()."
|
"Testing GeoJSON output from the database using GeoQuerySet.geojson()."
|
||||||
# Only PostGIS 1.3.4+ and SpatiaLite 3.0+ support GeoJSON.
|
# Only PostGIS and SpatiaLite 3.0+ support GeoJSON.
|
||||||
if not connection.ops.geojson:
|
if not connection.ops.geojson:
|
||||||
self.assertRaises(NotImplementedError, Country.objects.all().geojson, field_name='mpoly')
|
self.assertRaises(NotImplementedError, Country.objects.all().geojson, field_name='mpoly')
|
||||||
return
|
return
|
||||||
|
@ -520,17 +508,15 @@ class GeoQuerySetTest(TestCase):
|
||||||
# SELECT ST_AsGeoJson("geoapp_city"."point", 8, 0) FROM "geoapp_city" WHERE "geoapp_city"."name" = 'Pueblo';
|
# SELECT ST_AsGeoJson("geoapp_city"."point", 8, 0) FROM "geoapp_city" WHERE "geoapp_city"."name" = 'Pueblo';
|
||||||
self.assertEqual(pueblo_json, City.objects.geojson().get(name='Pueblo').geojson)
|
self.assertEqual(pueblo_json, City.objects.geojson().get(name='Pueblo').geojson)
|
||||||
|
|
||||||
# 1.3.x: SELECT ST_AsGeoJson("geoapp_city"."point", 8, 1) FROM "geoapp_city" WHERE "geoapp_city"."name" = 'Houston';
|
# SELECT ST_AsGeoJson("geoapp_city"."point", 8, 2) FROM "geoapp_city" WHERE "geoapp_city"."name" = 'Houston';
|
||||||
# 1.4.x: SELECT ST_AsGeoJson("geoapp_city"."point", 8, 2) FROM "geoapp_city" WHERE "geoapp_city"."name" = 'Houston';
|
|
||||||
# This time we want to include the CRS by using the `crs` keyword.
|
# This time we want to include the CRS by using the `crs` keyword.
|
||||||
self.assertEqual(houston_json, City.objects.geojson(crs=True, model_att='json').get(name='Houston').json)
|
self.assertEqual(houston_json, City.objects.geojson(crs=True, model_att='json').get(name='Houston').json)
|
||||||
|
|
||||||
# 1.3.x: SELECT ST_AsGeoJson("geoapp_city"."point", 8, 2) FROM "geoapp_city" WHERE "geoapp_city"."name" = 'Victoria';
|
# SELECT ST_AsGeoJson("geoapp_city"."point", 8, 1) FROM "geoapp_city" WHERE "geoapp_city"."name" = 'Houston';
|
||||||
# 1.4.x: SELECT ST_AsGeoJson("geoapp_city"."point", 8, 1) FROM "geoapp_city" WHERE "geoapp_city"."name" = 'Houston';
|
|
||||||
# This time we include the bounding box by using the `bbox` keyword.
|
# This time we include the bounding box by using the `bbox` keyword.
|
||||||
self.assertEqual(victoria_json, City.objects.geojson(bbox=True).get(name='Victoria').geojson)
|
self.assertEqual(victoria_json, City.objects.geojson(bbox=True).get(name='Victoria').geojson)
|
||||||
|
|
||||||
# 1.(3|4).x: SELECT ST_AsGeoJson("geoapp_city"."point", 5, 3) FROM "geoapp_city" WHERE "geoapp_city"."name" = 'Chicago';
|
# SELECT ST_AsGeoJson("geoapp_city"."point", 5, 3) FROM "geoapp_city" WHERE "geoapp_city"."name" = 'Chicago';
|
||||||
# Finally, we set every available keyword.
|
# Finally, we set every available keyword.
|
||||||
self.assertEqual(chicago_json, City.objects.geojson(bbox=True, crs=True, precision=5).get(name='Chicago').geojson)
|
self.assertEqual(chicago_json, City.objects.geojson(bbox=True, crs=True, precision=5).get(name='Chicago').geojson)
|
||||||
|
|
||||||
|
@ -581,9 +567,7 @@ class GeoQuerySetTest(TestCase):
|
||||||
self.assertEqual('<Point><coordinates>-104.609252,38.255001</coordinates></Point>', ptown.kml)
|
self.assertEqual('<Point><coordinates>-104.609252,38.255001</coordinates></Point>', ptown.kml)
|
||||||
|
|
||||||
# Only PostGIS has support for the MakeLine aggregate.
|
# Only PostGIS has support for the MakeLine aggregate.
|
||||||
@no_mysql
|
@skipUnlessDBFeature("has_make_line_method")
|
||||||
@no_oracle
|
|
||||||
@no_spatialite
|
|
||||||
def test_make_line(self):
|
def test_make_line(self):
|
||||||
"Testing the `make_line` GeoQuerySet method."
|
"Testing the `make_line` GeoQuerySet method."
|
||||||
# Ensuring that a `TypeError` is raised on models without PointFields.
|
# Ensuring that a `TypeError` is raised on models without PointFields.
|
||||||
|
@ -610,8 +594,7 @@ class GeoQuerySetTest(TestCase):
|
||||||
else:
|
else:
|
||||||
self.assertEqual(1, c.num_geom)
|
self.assertEqual(1, c.num_geom)
|
||||||
|
|
||||||
@no_mysql
|
@skipUnlessDBFeature("supports_num_points_poly")
|
||||||
@no_spatialite # SpatiaLite can only count vertices in LineStrings
|
|
||||||
def test_num_points(self):
|
def test_num_points(self):
|
||||||
"Testing the `num_points` GeoQuerySet method."
|
"Testing the `num_points` GeoQuerySet method."
|
||||||
for c in Country.objects.num_points():
|
for c in Country.objects.num_points():
|
||||||
|
@ -647,8 +630,7 @@ class GeoQuerySetTest(TestCase):
|
||||||
tol = 0.000000001
|
tol = 0.000000001
|
||||||
self.assertEqual(True, ref[c.name].equals_exact(c.point_on_surface, tol))
|
self.assertEqual(True, ref[c.name].equals_exact(c.point_on_surface, tol))
|
||||||
|
|
||||||
@no_mysql
|
@skipUnlessDBFeature("has_reverse_method")
|
||||||
@no_spatialite
|
|
||||||
def test_reverse_geom(self):
|
def test_reverse_geom(self):
|
||||||
"Testing GeoQuerySet.reverse_geom()."
|
"Testing GeoQuerySet.reverse_geom()."
|
||||||
coords = [(-95.363151, 29.763374), (-95.448601, 29.713803)]
|
coords = [(-95.363151, 29.763374), (-95.448601, 29.713803)]
|
||||||
|
@ -673,9 +655,7 @@ class GeoQuerySetTest(TestCase):
|
||||||
self.assertAlmostEqual(c1[0] * xfac, c2[0], tol)
|
self.assertAlmostEqual(c1[0] * xfac, c2[0], tol)
|
||||||
self.assertAlmostEqual(c1[1] * yfac, c2[1], tol)
|
self.assertAlmostEqual(c1[1] * yfac, c2[1], tol)
|
||||||
|
|
||||||
@no_mysql
|
@skipUnlessDBFeature("has_snap_to_grid_method")
|
||||||
@no_oracle
|
|
||||||
@no_spatialite
|
|
||||||
def test_snap_to_grid(self):
|
def test_snap_to_grid(self):
|
||||||
"Testing GeoQuerySet.snap_to_grid()."
|
"Testing GeoQuerySet.snap_to_grid()."
|
||||||
# Let's try and break snap_to_grid() with bad combinations of arguments.
|
# Let's try and break snap_to_grid() with bad combinations of arguments.
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.contrib.gis.geos import HAS_GEOS
|
from django.contrib.gis.geos import HAS_GEOS
|
||||||
from django.contrib.gis.tests.utils import mysql, no_mysql, no_oracle, no_spatialite
|
from django.contrib.gis.tests.utils import mysql, no_mysql, no_oracle
|
||||||
from django.test import TestCase, skipUnlessDBFeature
|
from django.test import TestCase, skipUnlessDBFeature
|
||||||
|
|
||||||
if HAS_GEOS:
|
if HAS_GEOS:
|
||||||
|
@ -60,8 +60,7 @@ class RelatedGeoModelTest(TestCase):
|
||||||
qs = list(City.objects.filter(name=name).transform(srid, field_name='location__point'))
|
qs = list(City.objects.filter(name=name).transform(srid, field_name='location__point'))
|
||||||
check_pnt(GEOSGeometry(wkt, srid), qs[0].location.point)
|
check_pnt(GEOSGeometry(wkt, srid), qs[0].location.point)
|
||||||
|
|
||||||
@no_mysql
|
@skipUnlessDBFeature("supports_extent_aggr")
|
||||||
@no_spatialite
|
|
||||||
def test04a_related_extent_aggregate(self):
|
def test04a_related_extent_aggregate(self):
|
||||||
"Testing the `extent` GeoQuerySet aggregates on related geographic models."
|
"Testing the `extent` GeoQuerySet aggregates on related geographic models."
|
||||||
# This combines the Extent and Union aggregates into one query
|
# This combines the Extent and Union aggregates into one query
|
||||||
|
@ -265,9 +264,7 @@ class RelatedGeoModelTest(TestCase):
|
||||||
# Should be `None`, and not a 'dummy' model.
|
# Should be `None`, and not a 'dummy' model.
|
||||||
self.assertEqual(None, b.author)
|
self.assertEqual(None, b.author)
|
||||||
|
|
||||||
@no_mysql
|
@skipUnlessDBFeature("supports_collect_aggr")
|
||||||
@no_oracle
|
|
||||||
@no_spatialite
|
|
||||||
def test14_collect(self):
|
def test14_collect(self):
|
||||||
"Testing the `collect` GeoQuerySet method and `Collect` aggregate."
|
"Testing the `collect` GeoQuerySet method and `Collect` aggregate."
|
||||||
# Reference query:
|
# Reference query:
|
||||||
|
|
|
@ -29,9 +29,6 @@ def no_mysql(func):
|
||||||
return no_backend(func, 'mysql')
|
return no_backend(func, 'mysql')
|
||||||
|
|
||||||
|
|
||||||
def no_spatialite(func):
|
|
||||||
return no_backend(func, 'spatialite')
|
|
||||||
|
|
||||||
# Shortcut booleans to omit only portions of tests.
|
# Shortcut booleans to omit only portions of tests.
|
||||||
_default_db = settings.DATABASES[DEFAULT_DB_ALIAS]['ENGINE'].rsplit('.')[-1]
|
_default_db = settings.DATABASES[DEFAULT_DB_ALIAS]['ENGINE'].rsplit('.')[-1]
|
||||||
oracle = _default_db == 'oracle'
|
oracle = _default_db == 'oracle'
|
||||||
|
|
|
@ -270,11 +270,11 @@ Method PostGIS Oracle SpatiaLite
|
||||||
==================================== ======= ====== ==========
|
==================================== ======= ====== ==========
|
||||||
:meth:`GeoQuerySet.area` X X X
|
:meth:`GeoQuerySet.area` X X X
|
||||||
:meth:`GeoQuerySet.centroid` X X X
|
:meth:`GeoQuerySet.centroid` X X X
|
||||||
:meth:`GeoQuerySet.collect` X
|
:meth:`GeoQuerySet.collect` X (from v3.0)
|
||||||
:meth:`GeoQuerySet.difference` X X X
|
:meth:`GeoQuerySet.difference` X X X
|
||||||
:meth:`GeoQuerySet.distance` X X X
|
:meth:`GeoQuerySet.distance` X X X
|
||||||
:meth:`GeoQuerySet.envelope` X X
|
:meth:`GeoQuerySet.envelope` X X
|
||||||
:meth:`GeoQuerySet.extent` X X
|
:meth:`GeoQuerySet.extent` X X (from v3.0)
|
||||||
:meth:`GeoQuerySet.extent3d` X
|
:meth:`GeoQuerySet.extent3d` X
|
||||||
:meth:`GeoQuerySet.force_rhr` X
|
:meth:`GeoQuerySet.force_rhr` X
|
||||||
:meth:`GeoQuerySet.geohash` X
|
:meth:`GeoQuerySet.geohash` X
|
||||||
|
|
|
@ -83,6 +83,9 @@ Minor features
|
||||||
* Compatibility shims for ``SpatialRefSys`` and ``GeometryColumns`` changed in
|
* Compatibility shims for ``SpatialRefSys`` and ``GeometryColumns`` changed in
|
||||||
Django 1.2 have been removed.
|
Django 1.2 have been removed.
|
||||||
|
|
||||||
|
* The Spatialite backend now supports ``Collect`` and ``Extent`` aggregates
|
||||||
|
when the database version is 3.0 or later.
|
||||||
|
|
||||||
:mod:`django.contrib.messages`
|
:mod:`django.contrib.messages`
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue