Fixed #26753 -- Made GDAL a required dependency for contrib.gis
Thanks Tim Graham for the review.
This commit is contained in:
parent
7def55c3f6
commit
f7a363ee1d
|
@ -1,8 +1,7 @@
|
|||
from django.contrib.admin import ModelAdmin
|
||||
from django.contrib.gis.admin.widgets import OpenLayersWidget
|
||||
from django.contrib.gis.db import models
|
||||
from django.contrib.gis.gdal import HAS_GDAL, OGRGeomType
|
||||
from django.core.exceptions import ImproperlyConfigured
|
||||
from django.contrib.gis.gdal import OGRGeomType
|
||||
|
||||
spherical_mercator_srid = 3857
|
||||
|
||||
|
@ -59,12 +58,6 @@ class GeoModelAdmin(ModelAdmin):
|
|||
3D editing).
|
||||
"""
|
||||
if isinstance(db_field, models.GeometryField) and db_field.dim < 3:
|
||||
if not HAS_GDAL and db_field.srid != self.map_srid:
|
||||
raise ImproperlyConfigured(
|
||||
"Map SRID is %s and SRID of `%s` is %s. GDAL must be "
|
||||
"installed to perform the transformation."
|
||||
% (self.map_srid, db_field, db_field.srid)
|
||||
)
|
||||
# Setting the widget with the newly defined widget.
|
||||
kwargs['widget'] = self.get_map_widget(db_field)
|
||||
return db_field.formfield(**kwargs)
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
import re
|
||||
|
||||
from django.contrib.gis import gdal
|
||||
from django.utils import six
|
||||
from django.utils.encoding import python_2_unicode_compatible
|
||||
|
@ -11,47 +9,32 @@ class SpatialRefSysMixin(object):
|
|||
The SpatialRefSysMixin is a class used by the database-dependent
|
||||
SpatialRefSys objects to reduce redundant code.
|
||||
"""
|
||||
# For pulling out the spheroid from the spatial reference string. This
|
||||
# regular expression is used only if the user does not have GDAL installed.
|
||||
# TODO: Flattening not used in all ellipsoids, could also be a minor axis,
|
||||
# or 'b' parameter.
|
||||
spheroid_regex = re.compile(r'.+SPHEROID\[\"(?P<name>.+)\",(?P<major>\d+(\.\d+)?),(?P<flattening>\d{3}\.\d+),')
|
||||
|
||||
# For pulling out the units on platforms w/o GDAL installed.
|
||||
# TODO: Figure out how to pull out angular units of projected coordinate system and
|
||||
# fix for LOCAL_CS types. GDAL should be highly recommended for performing
|
||||
# distance queries.
|
||||
units_regex = re.compile(r'.+UNIT ?\["(?P<unit_name>[\w \.\'\(\)]+)", ?(?P<unit>[^ ,\]]+)', re.DOTALL)
|
||||
|
||||
@property
|
||||
def srs(self):
|
||||
"""
|
||||
Returns a GDAL SpatialReference object, if GDAL is installed.
|
||||
Returns a GDAL SpatialReference object.
|
||||
"""
|
||||
if gdal.HAS_GDAL:
|
||||
# TODO: Is caching really necessary here? Is complexity worth it?
|
||||
if hasattr(self, '_srs'):
|
||||
# Returning a clone of the cached SpatialReference object.
|
||||
return self._srs.clone()
|
||||
else:
|
||||
# Attempting to cache a SpatialReference object.
|
||||
|
||||
# Trying to get from WKT first.
|
||||
try:
|
||||
self._srs = gdal.SpatialReference(self.wkt)
|
||||
return self.srs
|
||||
except Exception as e:
|
||||
msg = e
|
||||
|
||||
try:
|
||||
self._srs = gdal.SpatialReference(self.proj4text)
|
||||
return self.srs
|
||||
except Exception as e:
|
||||
msg = e
|
||||
|
||||
raise Exception('Could not get OSR SpatialReference from WKT: %s\nError:\n%s' % (self.wkt, msg))
|
||||
# TODO: Is caching really necessary here? Is complexity worth it?
|
||||
if hasattr(self, '_srs'):
|
||||
# Returning a clone of the cached SpatialReference object.
|
||||
return self._srs.clone()
|
||||
else:
|
||||
raise Exception('GDAL is not installed.')
|
||||
# Attempting to cache a SpatialReference object.
|
||||
|
||||
# Trying to get from WKT first.
|
||||
try:
|
||||
self._srs = gdal.SpatialReference(self.wkt)
|
||||
return self.srs
|
||||
except Exception as e:
|
||||
msg = e
|
||||
|
||||
try:
|
||||
self._srs = gdal.SpatialReference(self.proj4text)
|
||||
return self.srs
|
||||
except Exception as e:
|
||||
msg = e
|
||||
|
||||
raise Exception('Could not get OSR SpatialReference from WKT: %s\nError:\n%s' % (self.wkt, msg))
|
||||
|
||||
@property
|
||||
def ellipsoid(self):
|
||||
|
@ -59,14 +42,7 @@ class SpatialRefSysMixin(object):
|
|||
Returns a tuple of the ellipsoid parameters:
|
||||
(semimajor axis, semiminor axis, and inverse flattening).
|
||||
"""
|
||||
if gdal.HAS_GDAL:
|
||||
return self.srs.ellipsoid
|
||||
else:
|
||||
m = self.spheroid_regex.match(self.wkt)
|
||||
if m:
|
||||
return (float(m.group('major')), float(m.group('flattening')))
|
||||
else:
|
||||
return None
|
||||
return self.srs.ellipsoid
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
|
@ -86,70 +62,37 @@ class SpatialRefSysMixin(object):
|
|||
@property
|
||||
def projected(self):
|
||||
"Is this Spatial Reference projected?"
|
||||
if gdal.HAS_GDAL:
|
||||
return self.srs.projected
|
||||
else:
|
||||
return self.wkt.startswith('PROJCS')
|
||||
return self.srs.projected
|
||||
|
||||
@property
|
||||
def local(self):
|
||||
"Is this Spatial Reference local?"
|
||||
if gdal.HAS_GDAL:
|
||||
return self.srs.local
|
||||
else:
|
||||
return self.wkt.startswith('LOCAL_CS')
|
||||
return self.srs.local
|
||||
|
||||
@property
|
||||
def geographic(self):
|
||||
"Is this Spatial Reference geographic?"
|
||||
if gdal.HAS_GDAL:
|
||||
return self.srs.geographic
|
||||
else:
|
||||
return self.wkt.startswith('GEOGCS')
|
||||
return self.srs.geographic
|
||||
|
||||
@property
|
||||
def linear_name(self):
|
||||
"Returns the linear units name."
|
||||
if gdal.HAS_GDAL:
|
||||
return self.srs.linear_name
|
||||
elif self.geographic:
|
||||
return None
|
||||
else:
|
||||
m = self.units_regex.match(self.wkt)
|
||||
return m.group('unit_name')
|
||||
return self.srs.linear_name
|
||||
|
||||
@property
|
||||
def linear_units(self):
|
||||
"Returns the linear units."
|
||||
if gdal.HAS_GDAL:
|
||||
return self.srs.linear_units
|
||||
elif self.geographic:
|
||||
return None
|
||||
else:
|
||||
m = self.units_regex.match(self.wkt)
|
||||
return m.group('unit')
|
||||
return self.srs.linear_units
|
||||
|
||||
@property
|
||||
def angular_name(self):
|
||||
"Returns the name of the angular units."
|
||||
if gdal.HAS_GDAL:
|
||||
return self.srs.angular_name
|
||||
elif self.projected:
|
||||
return None
|
||||
else:
|
||||
m = self.units_regex.match(self.wkt)
|
||||
return m.group('unit_name')
|
||||
return self.srs.angular_name
|
||||
|
||||
@property
|
||||
def angular_units(self):
|
||||
"Returns the angular units."
|
||||
if gdal.HAS_GDAL:
|
||||
return self.srs.angular_units
|
||||
elif self.projected:
|
||||
return None
|
||||
else:
|
||||
m = self.units_regex.match(self.wkt)
|
||||
return m.group('unit')
|
||||
return self.srs.angular_units
|
||||
|
||||
@property
|
||||
def units(self):
|
||||
|
@ -167,11 +110,7 @@ class SpatialRefSysMixin(object):
|
|||
Return a tuple of (unit_value, unit_name) for the given WKT without
|
||||
using any of the database fields.
|
||||
"""
|
||||
if gdal.HAS_GDAL:
|
||||
return gdal.SpatialReference(wkt).units
|
||||
else:
|
||||
m = cls.units_regex.match(wkt)
|
||||
return float(m.group('unit')), m.group('unit_name')
|
||||
return gdal.SpatialReference(wkt).units
|
||||
|
||||
@classmethod
|
||||
def get_spheroid(cls, wkt, string=True):
|
||||
|
@ -179,17 +118,9 @@ class SpatialRefSysMixin(object):
|
|||
Class method used by GeometryField on initialization to
|
||||
retrieve the `SPHEROID[..]` parameters from the given WKT.
|
||||
"""
|
||||
if gdal.HAS_GDAL:
|
||||
srs = gdal.SpatialReference(wkt)
|
||||
sphere_params = srs.ellipsoid
|
||||
sphere_name = srs['spheroid']
|
||||
else:
|
||||
m = cls.spheroid_regex.match(wkt)
|
||||
if m:
|
||||
sphere_params = (float(m.group('major')), float(m.group('flattening')))
|
||||
sphere_name = m.group('name')
|
||||
else:
|
||||
return None
|
||||
srs = gdal.SpatialReference(wkt)
|
||||
sphere_params = srs.ellipsoid
|
||||
sphere_name = srs['spheroid']
|
||||
|
||||
if not string:
|
||||
return sphere_name, sphere_params
|
||||
|
@ -203,10 +134,6 @@ class SpatialRefSysMixin(object):
|
|||
|
||||
def __str__(self):
|
||||
"""
|
||||
Returns the string representation. If GDAL is installed,
|
||||
it will be 'pretty' OGC WKT.
|
||||
Returns the string representation, a 'pretty' OGC WKT.
|
||||
"""
|
||||
try:
|
||||
return six.text_type(self.srs)
|
||||
except Exception:
|
||||
return six.text_type(self.wkt)
|
||||
return six.text_type(self.srs)
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
from django.contrib.gis import forms
|
||||
from django.contrib.gis import forms, gdal
|
||||
from django.contrib.gis.db.models.lookups import (
|
||||
RasterBandTransform, gis_lookups,
|
||||
)
|
||||
from django.contrib.gis.db.models.proxy import SpatialProxy
|
||||
from django.contrib.gis.gdal import HAS_GDAL
|
||||
from django.contrib.gis.gdal.error import GDALException
|
||||
from django.contrib.gis.geometry.backend import Geometry, GeometryException
|
||||
from django.core.exceptions import ImproperlyConfigured
|
||||
|
@ -186,18 +185,16 @@ class BaseSpatialField(Field):
|
|||
"""
|
||||
Return a GDALRaster if conversion is successful, otherwise return None.
|
||||
"""
|
||||
from django.contrib.gis.gdal import GDALRaster
|
||||
|
||||
if isinstance(value, GDALRaster):
|
||||
if isinstance(value, gdal.GDALRaster):
|
||||
return value
|
||||
elif is_candidate:
|
||||
try:
|
||||
return GDALRaster(value)
|
||||
return gdal.GDALRaster(value)
|
||||
except GDALException:
|
||||
pass
|
||||
elif isinstance(value, dict):
|
||||
try:
|
||||
return GDALRaster(value)
|
||||
return gdal.GDALRaster(value)
|
||||
except GDALException:
|
||||
raise ValueError("Couldn't create spatial object from lookup value '%s'." % value)
|
||||
|
||||
|
@ -228,10 +225,8 @@ class BaseSpatialField(Field):
|
|||
else:
|
||||
# Check if input is a candidate for conversion to raster or geometry.
|
||||
is_candidate = isinstance(obj, (bytes, six.string_types)) or hasattr(obj, '__geo_interface__')
|
||||
# With GDAL installed, try to convert the input to raster.
|
||||
raster = False
|
||||
if HAS_GDAL:
|
||||
raster = self.get_raster_prep_value(obj, is_candidate)
|
||||
# Try to convert the input to raster.
|
||||
raster = self.get_raster_prep_value(obj, is_candidate)
|
||||
|
||||
if raster:
|
||||
obj = raster
|
||||
|
@ -425,11 +420,6 @@ class RasterField(BaseSpatialField):
|
|||
geom_type = 'RASTER'
|
||||
geography = False
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
if not HAS_GDAL:
|
||||
raise ImproperlyConfigured('RasterField requires GDAL.')
|
||||
super(RasterField, self).__init__(*args, **kwargs)
|
||||
|
||||
def _check_connection(self, connection):
|
||||
# Make sure raster fields are used only on backends with raster support.
|
||||
if not connection.features.gis_enabled or not connection.features.supports_raster:
|
||||
|
@ -451,13 +441,11 @@ class RasterField(BaseSpatialField):
|
|||
|
||||
def contribute_to_class(self, cls, name, **kwargs):
|
||||
super(RasterField, self).contribute_to_class(cls, name, **kwargs)
|
||||
# Importing GDALRaster raises an exception on systems without gdal.
|
||||
from django.contrib.gis.gdal import GDALRaster
|
||||
# Setup for lazy-instantiated Raster object. For large querysets, the
|
||||
# instantiation of all GDALRasters can potentially be expensive. This
|
||||
# delays the instantiation of the objects to the moment of evaluation
|
||||
# of the raster attribute.
|
||||
setattr(cls, self.attname, SpatialProxy(GDALRaster, self))
|
||||
setattr(cls, self.attname, SpatialProxy(gdal.GDALRaster, self))
|
||||
|
||||
def get_transform(self, name):
|
||||
try:
|
||||
|
|
|
@ -91,6 +91,7 @@ class OSMWidget(BaseGeometryWidget):
|
|||
template_name = 'gis/openlayers-osm.html'
|
||||
default_lon = 5
|
||||
default_lat = 47
|
||||
map_srid = 3857
|
||||
|
||||
class Media:
|
||||
js = (
|
||||
|
@ -104,12 +105,3 @@ class OSMWidget(BaseGeometryWidget):
|
|||
self.attrs[key] = getattr(self, key)
|
||||
if attrs:
|
||||
self.attrs.update(attrs)
|
||||
|
||||
@property
|
||||
def map_srid(self):
|
||||
# Use the official spherical mercator projection SRID when GDAL is
|
||||
# available; otherwise, fallback to 900913.
|
||||
if gdal.HAS_GDAL:
|
||||
return 3857
|
||||
else:
|
||||
return 900913
|
||||
|
|
|
@ -24,12 +24,6 @@
|
|||
library name for the current OS. The default library path may be overridden
|
||||
by setting `GDAL_LIBRARY_PATH` in your settings with the path to the GDAL C
|
||||
library on your system.
|
||||
|
||||
GDAL links to a large number of external libraries that consume RAM when
|
||||
loaded. Thus, it may desirable to disable GDAL on systems with limited
|
||||
RAM resources -- this may be accomplished by setting `GDAL_LIBRARY_PATH`
|
||||
to a non-existent file location (e.g., `GDAL_LIBRARY_PATH='/null/path'`;
|
||||
setting to None/False/'' will not work as a string must be given).
|
||||
"""
|
||||
from django.contrib.gis.gdal.envelope import Envelope
|
||||
from django.contrib.gis.gdal.error import ( # NOQA
|
||||
|
|
|
@ -64,8 +64,6 @@ class GEOSGeometry(GEOSBase, ListMixin):
|
|||
g = wkb_r().read(force_bytes(geo_input))
|
||||
elif json_regex.match(geo_input):
|
||||
# Handling GeoJSON input.
|
||||
if not gdal.HAS_GDAL:
|
||||
raise ValueError('Initializing geometry from JSON input requires GDAL.')
|
||||
g = wkb_r().read(gdal.OGRGeometry(geo_input).wkb)
|
||||
else:
|
||||
raise ValueError('String or unicode input unrecognized as WKT EWKT, and HEXEWKB.')
|
||||
|
@ -476,8 +474,6 @@ class GEOSGeometry(GEOSBase, ListMixin):
|
|||
@property
|
||||
def ogr(self):
|
||||
"Returns the OGR Geometry for this Geometry."
|
||||
if not gdal.HAS_GDAL:
|
||||
raise GEOSException('GDAL required to convert to an OGRGeometry.')
|
||||
if self.srid:
|
||||
try:
|
||||
return gdal.OGRGeometry(self.wkb, self.srid)
|
||||
|
@ -488,8 +484,6 @@ class GEOSGeometry(GEOSBase, ListMixin):
|
|||
@property
|
||||
def srs(self):
|
||||
"Returns the OSR SpatialReference for SRID of this Geometry."
|
||||
if not gdal.HAS_GDAL:
|
||||
raise GEOSException('GDAL required to return a SpatialReference object.')
|
||||
if self.srid:
|
||||
try:
|
||||
return gdal.SpatialReference(self.srid)
|
||||
|
@ -520,9 +514,6 @@ class GEOSGeometry(GEOSBase, ListMixin):
|
|||
else:
|
||||
return
|
||||
|
||||
if not gdal.HAS_GDAL:
|
||||
raise GEOSException("GDAL library is not available to transform() geometry.")
|
||||
|
||||
if isinstance(ct, gdal.CoordTransform):
|
||||
# We don't care about SRID because CoordTransform presupposes
|
||||
# source SRS.
|
||||
|
|
|
@ -98,8 +98,6 @@ class Command(BaseCommand):
|
|||
|
||||
def handle(self, *args, **options):
|
||||
data_source, model_name = options.pop('data_source'), options.pop('model_name')
|
||||
if not gdal.HAS_GDAL:
|
||||
raise CommandError('GDAL is required to inspect geospatial data sources.')
|
||||
|
||||
# Getting the OGR DataSource from the string parameter.
|
||||
try:
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
from __future__ import unicode_literals
|
||||
|
||||
from django.contrib.gis.gdal import HAS_GDAL
|
||||
from django.core.serializers.base import (
|
||||
SerializationError, SerializerDoesNotExist,
|
||||
)
|
||||
from django.core.serializers.base import SerializerDoesNotExist
|
||||
from django.core.serializers.json import Serializer as JSONSerializer
|
||||
|
||||
if HAS_GDAL:
|
||||
|
@ -53,10 +51,6 @@ class Serializer(JSONSerializer):
|
|||
if self._geometry:
|
||||
if self._geometry.srid != self.srid:
|
||||
# If needed, transform the geometry in the srid of the global geojson srid
|
||||
if not HAS_GDAL:
|
||||
raise SerializationError(
|
||||
'Unable to convert geometry to SRID %s when GDAL is not installed.' % self.srid
|
||||
)
|
||||
if self._geometry.srid not in self._cts:
|
||||
srs = SpatialReference(self.srid)
|
||||
self._cts[self._geometry.srid] = CoordTransform(self._geometry.srs, srs)
|
||||
|
|
|
@ -91,9 +91,9 @@ transform procedure::
|
|||
|
||||
Thus, geometry parameters may be passed in using the ``GEOSGeometry`` object, WKT
|
||||
(Well Known Text [#fnwkt]_), HEXEWKB (PostGIS specific -- a WKB geometry in
|
||||
hexadecimal [#fnewkb]_), and GeoJSON [#fngeojson]_ (requires GDAL). Essentially,
|
||||
if the input is not a ``GEOSGeometry`` object, the geometry field will attempt to
|
||||
create a ``GEOSGeometry`` instance from the input.
|
||||
hexadecimal [#fnewkb]_), and GeoJSON [#fngeojson]_. Essentially, if the input is
|
||||
not a ``GEOSGeometry`` object, the geometry field will attempt to create a
|
||||
``GEOSGeometry`` instance from the input.
|
||||
|
||||
For more information creating :class:`~django.contrib.gis.geos.GEOSGeometry`
|
||||
objects, refer to the :ref:`GEOS tutorial <geos-tutorial>`.
|
||||
|
|
|
@ -195,7 +195,7 @@ Format Input Type
|
|||
WKT / EWKT ``str`` or ``unicode``
|
||||
HEX / HEXEWKB ``str`` or ``unicode``
|
||||
WKB / EWKB ``buffer``
|
||||
GeoJSON (requires GDAL) ``str`` or ``unicode``
|
||||
GeoJSON ``str`` or ``unicode``
|
||||
======================= ======================
|
||||
|
||||
Properties
|
||||
|
@ -345,10 +345,6 @@ another object.
|
|||
Returns an :class:`~django.contrib.gis.gdal.OGRGeometry` object
|
||||
corresponding to the GEOS geometry.
|
||||
|
||||
.. note::
|
||||
|
||||
Requires GDAL.
|
||||
|
||||
.. _wkb:
|
||||
|
||||
.. attribute:: GEOSGeometry.wkb
|
||||
|
@ -618,10 +614,6 @@ Other Properties & Methods
|
|||
Returns a :class:`~django.contrib.gis.gdal.SpatialReference` object
|
||||
corresponding to the SRID of the geometry or ``None``.
|
||||
|
||||
.. note::
|
||||
|
||||
Requires GDAL.
|
||||
|
||||
.. method:: GEOSGeometry.transform(ct, clone=False)
|
||||
|
||||
Transforms the geometry according to the given coordinate transformation
|
||||
|
@ -635,10 +627,10 @@ Other Properties & Methods
|
|||
|
||||
.. note::
|
||||
|
||||
Requires GDAL. Raises :class:`~django.contrib.gis.geos.GEOSException` if
|
||||
GDAL is not available or if the geometry's SRID is ``None`` or less than
|
||||
0. It doesn't impose any constraints on the geometry's SRID if called
|
||||
with a :class:`~django.contrib.gis.gdal.CoordTransform` object.
|
||||
Raises :class:`~django.contrib.gis.geos.GEOSException` if GDAL is not
|
||||
available or if the geometry's SRID is ``None`` or less than 0. It
|
||||
doesn't impose any constraints on the geometry's SRID if called with a
|
||||
:class:`~django.contrib.gis.gdal.CoordTransform` object.
|
||||
|
||||
.. versionchanged:: 1.10
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ Program Description Required
|
|||
======================== ==================================== ================================ ===================================
|
||||
:doc:`GEOS <../geos>` Geometry Engine Open Source Yes 3.4, 3.3
|
||||
`PROJ.4`_ Cartographic Projections library Yes (PostgreSQL and SQLite only) 4.9, 4.8, 4.7, 4.6, 4.5, 4.4
|
||||
:doc:`GDAL <../gdal>` Geospatial Data Abstraction Library Yes (SQLite only) 2.1, 2.0, 1.11, 1.10, 1.9, 1.8, 1.7
|
||||
:doc:`GDAL <../gdal>` Geospatial Data Abstraction Library Yes 2.1, 2.0, 1.11, 1.10, 1.9, 1.8, 1.7
|
||||
:doc:`GeoIP <../geoip>` IP-based geolocation library No 1.4
|
||||
`PostGIS`__ Spatial extensions for PostgreSQL Yes (PostgreSQL only) 2.2, 2.1
|
||||
`SpatiaLite`__ Spatial extensions for SQLite Yes (SQLite only) 4.3, 4.2, 4.1, 4.0
|
||||
|
@ -19,6 +19,11 @@ Program Description Required
|
|||
Note that older or more recent versions of these libraries *may* also work
|
||||
totally fine with GeoDjango. Your mileage may vary.
|
||||
|
||||
.. versionchanged:: 1.11
|
||||
|
||||
In older versions, GDAL is required only for SQLite. Now it's required for
|
||||
all databases.
|
||||
|
||||
..
|
||||
Libs release dates:
|
||||
GEOS 3.3.0 2011-05-30
|
||||
|
@ -37,13 +42,6 @@ totally fine with GeoDjango. Your mileage may vary.
|
|||
Spatialite 4.2.0 2014-07-25
|
||||
Spatialite 4.3.0 2015-09-07
|
||||
|
||||
.. admonition:: Install GDAL
|
||||
|
||||
While :ref:`gdalbuild` is technically not required, it is *recommended*.
|
||||
Important features of GeoDjango (including the :doc:`../layermapping`,
|
||||
geometry reprojection, and the geographic admin) depend on its
|
||||
functionality.
|
||||
|
||||
.. note::
|
||||
|
||||
The GeoDjango interfaces to GEOS, GDAL, and GeoIP may be used
|
||||
|
|
|
@ -58,9 +58,9 @@ supported versions, and any notes for each of the supported database backends:
|
|||
================== ============================== ================== =========================================
|
||||
Database Library Requirements Supported Versions Notes
|
||||
================== ============================== ================== =========================================
|
||||
PostgreSQL GEOS, PROJ.4, PostGIS 9.3+ Requires PostGIS.
|
||||
MySQL GEOS 5.5+ Not OGC-compliant; :ref:`limited functionality <mysql-spatial-limitations>`.
|
||||
Oracle GEOS 11.2+ XE not supported.
|
||||
PostgreSQL GEOS, GDAL, PROJ.4, PostGIS 9.3+ Requires PostGIS.
|
||||
MySQL GEOS, GDAL 5.5+ Not OGC-compliant; :ref:`limited functionality <mysql-spatial-limitations>`.
|
||||
Oracle GEOS, GDAL 11.2+ XE not supported.
|
||||
SQLite GEOS, GDAL, PROJ.4, SpatiaLite 3.6.+ Requires SpatiaLite 4.0+, pysqlite2 2.5+
|
||||
================== ============================== ================== =========================================
|
||||
|
||||
|
|
|
@ -8,10 +8,6 @@
|
|||
GeoDjango provides a specific serializer for the `GeoJSON`__ format. See
|
||||
:doc:`/topics/serialization` for more information on serialization.
|
||||
|
||||
The GDAL library is required if any of the serialized geometries need
|
||||
coordinate transformations (that is if the geometry's spatial reference system
|
||||
differs from the ``srid`` serializer option).
|
||||
|
||||
__ http://geojson.org/
|
||||
|
||||
The ``geojson`` serializer is not meant for round-tripping data, as it has no
|
||||
|
|
|
@ -668,7 +668,7 @@ for popular geospatial formats::
|
|||
MULTIPOLYGON (((12.4157980000000006 43.9579540000000009, 12.4505540000000003 43.9797209999999978, ...
|
||||
>>> sm.mpoly.wkb # WKB (as Python binary buffer)
|
||||
<read-only buffer for 0x1fe2c70, size -1, offset 0 at 0x2564c40>
|
||||
>>> sm.mpoly.geojson # GeoJSON (requires GDAL)
|
||||
>>> sm.mpoly.geojson # GeoJSON
|
||||
'{ "type": "MultiPolygon", "coordinates": [ [ [ [ 12.415798, 43.957954 ], [ 12.450554, 43.979721 ], ...
|
||||
|
||||
This includes access to all of the advanced geometric operations provided by
|
||||
|
@ -753,13 +753,8 @@ This provides more context (including street and thoroughfare details) than
|
|||
available with the :class:`~django.contrib.gis.admin.GeoModelAdmin`
|
||||
(which uses the `Vector Map Level 0`_ WMS dataset hosted at `OSGeo`_).
|
||||
|
||||
First, there are some important requirements:
|
||||
|
||||
* :class:`~django.contrib.gis.admin.OSMGeoAdmin` requires that
|
||||
:doc:`GDAL <gdal>` is installed.
|
||||
|
||||
* The PROJ.4 datum shifting files must be installed (see the
|
||||
:ref:`PROJ.4 installation instructions <proj4>` for more details).
|
||||
The PROJ.4 datum shifting files must be installed (see the :ref:`PROJ.4
|
||||
installation instructions <proj4>` for more details).
|
||||
|
||||
If you meet this requirement, then just substitute the ``OSMGeoAdmin``
|
||||
option class in your ``admin.py`` file::
|
||||
|
|
|
@ -227,6 +227,13 @@ Validators
|
|||
Backwards incompatible changes in 1.11
|
||||
======================================
|
||||
|
||||
:mod:`django.contrib.gis`
|
||||
-------------------------
|
||||
|
||||
* To simplify the codebase and because it's easier to install than when
|
||||
``contrib.gis`` was first released, :ref:`gdalbuild` is now a required
|
||||
dependency for GeoDjango. In older versions, it's only required for SQLite.
|
||||
|
||||
Database backend API
|
||||
--------------------
|
||||
|
||||
|
|
|
@ -1,16 +1,13 @@
|
|||
from __future__ import unicode_literals
|
||||
|
||||
from unittest import skipUnless
|
||||
|
||||
from django.contrib.gis.db.models.functions import (
|
||||
Area, Distance, Length, Perimeter, Transform,
|
||||
)
|
||||
from django.contrib.gis.gdal import HAS_GDAL
|
||||
from django.contrib.gis.geos import GEOSGeometry, LineString, Point
|
||||
from django.contrib.gis.measure import D # alias for Distance
|
||||
from django.db import connection
|
||||
from django.db.models import F, Q
|
||||
from django.test import TestCase, ignore_warnings, mock, skipUnlessDBFeature
|
||||
from django.test import TestCase, ignore_warnings, skipUnlessDBFeature
|
||||
from django.utils.deprecation import RemovedInDjango20Warning
|
||||
|
||||
from ..utils import no_oracle, oracle, postgis
|
||||
|
@ -497,7 +494,6 @@ class DistanceFunctionsTests(TestCase):
|
|||
tol
|
||||
)
|
||||
|
||||
@skipUnless(HAS_GDAL, "GDAL is required.")
|
||||
@skipUnlessDBFeature("has_Distance_function", "has_Transform_function")
|
||||
def test_distance_projected(self):
|
||||
"""
|
||||
|
@ -520,26 +516,24 @@ class DistanceFunctionsTests(TestCase):
|
|||
455411.438904354, 519386.252102563, 696139.009211594,
|
||||
232513.278304279, 542445.630586414, 456679.155883207]
|
||||
|
||||
for has_gdal in [False, True]:
|
||||
with mock.patch('django.contrib.gis.gdal.HAS_GDAL', has_gdal):
|
||||
# Testing using different variations of parameters and using models
|
||||
# with different projected coordinate systems.
|
||||
dist1 = SouthTexasCity.objects.annotate(distance=Distance('point', lagrange)).order_by('id')
|
||||
if oracle:
|
||||
dist_qs = [dist1]
|
||||
else:
|
||||
dist2 = SouthTexasCityFt.objects.annotate(distance=Distance('point', lagrange)).order_by('id')
|
||||
dist_qs = [dist1, dist2]
|
||||
# Testing using different variations of parameters and using models
|
||||
# with different projected coordinate systems.
|
||||
dist1 = SouthTexasCity.objects.annotate(distance=Distance('point', lagrange)).order_by('id')
|
||||
if oracle:
|
||||
dist_qs = [dist1]
|
||||
else:
|
||||
dist2 = SouthTexasCityFt.objects.annotate(distance=Distance('point', lagrange)).order_by('id')
|
||||
dist_qs = [dist1, dist2]
|
||||
|
||||
# Original query done on PostGIS, have to adjust AlmostEqual tolerance
|
||||
# for Oracle.
|
||||
tol = 2 if oracle else 5
|
||||
# Original query done on PostGIS, have to adjust AlmostEqual tolerance
|
||||
# for Oracle.
|
||||
tol = 2 if oracle else 5
|
||||
|
||||
# Ensuring expected distances are returned for each distance queryset.
|
||||
for qs in dist_qs:
|
||||
for i, c in enumerate(qs):
|
||||
self.assertAlmostEqual(m_distances[i], c.distance.m, tol)
|
||||
self.assertAlmostEqual(ft_distances[i], c.distance.survey_ft, tol)
|
||||
# Ensuring expected distances are returned for each distance queryset.
|
||||
for qs in dist_qs:
|
||||
for i, c in enumerate(qs):
|
||||
self.assertAlmostEqual(m_distances[i], c.distance.m, tol)
|
||||
self.assertAlmostEqual(ft_distances[i], c.distance.survey_ft, tol)
|
||||
|
||||
@skipUnlessDBFeature("has_Distance_function", "supports_distance_geodetic")
|
||||
def test_distance_geodetic(self):
|
||||
|
|
|
@ -2,13 +2,11 @@ from __future__ import unicode_literals
|
|||
|
||||
import os
|
||||
import re
|
||||
from unittest import skipUnless
|
||||
|
||||
from django.contrib.gis.db.models import Extent3D, Union
|
||||
from django.contrib.gis.db.models.functions import (
|
||||
AsGeoJSON, AsKML, Length, Perimeter, Scale, Translate,
|
||||
)
|
||||
from django.contrib.gis.gdal import HAS_GDAL
|
||||
from django.contrib.gis.geos import GEOSGeometry, LineString, Point, Polygon
|
||||
from django.test import TestCase, ignore_warnings, skipUnlessDBFeature
|
||||
from django.utils._os import upath
|
||||
|
@ -19,10 +17,6 @@ from .models import (
|
|||
MultiPoint3D, Point2D, Point3D, Polygon2D, Polygon3D,
|
||||
)
|
||||
|
||||
if HAS_GDAL:
|
||||
from django.contrib.gis.utils import LayerMapping, LayerMapError
|
||||
|
||||
|
||||
data_path = os.path.realpath(os.path.join(os.path.dirname(upath(__file__)), '..', 'data'))
|
||||
city_file = os.path.join(data_path, 'cities', 'cities.shp')
|
||||
vrt_file = os.path.join(data_path, 'test_vrt', 'test_vrt.vrt')
|
||||
|
@ -101,7 +95,6 @@ class Geo3DLoadingHelper(object):
|
|||
Polygon3D.objects.create(name='3D BBox', poly=bbox_3d)
|
||||
|
||||
|
||||
@skipUnless(HAS_GDAL, "GDAL is required for Geo3DTest.")
|
||||
@skipUnlessDBFeature("gis_enabled", "supports_3d_storage")
|
||||
class Geo3DTest(Geo3DLoadingHelper, TestCase):
|
||||
"""
|
||||
|
@ -147,6 +140,9 @@ class Geo3DTest(Geo3DLoadingHelper, TestCase):
|
|||
"""
|
||||
Testing LayerMapping on 3D models.
|
||||
"""
|
||||
# Import here as GDAL is required for those imports
|
||||
from django.contrib.gis.utils import LayerMapping, LayerMapError
|
||||
|
||||
point_mapping = {'point': 'POINT'}
|
||||
mpoint_mapping = {'mpoint': 'MULTIPOINT'}
|
||||
|
||||
|
@ -310,7 +306,6 @@ class Geo3DTest(Geo3DLoadingHelper, TestCase):
|
|||
self.assertEqual(city_dict[city.name][2] + ztrans, city.translate.z)
|
||||
|
||||
|
||||
@skipUnless(HAS_GDAL, "GDAL is required for Geo3DTest.")
|
||||
@skipUnlessDBFeature("gis_enabled", "supports_3d_functions")
|
||||
class Geo3DFunctionsTests(Geo3DLoadingHelper, TestCase):
|
||||
def test_kml(self):
|
||||
|
|
|
@ -17,17 +17,5 @@ class City(models.Model):
|
|||
return self.name
|
||||
|
||||
|
||||
@python_2_unicode_compatible
|
||||
class CityMercator(models.Model):
|
||||
name = models.CharField(max_length=30)
|
||||
point = models.PointField(srid=3857)
|
||||
|
||||
class Meta:
|
||||
required_db_features = ['gis_enabled']
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
site = admin.AdminSite(name='admin_gis')
|
||||
site.register(City, admin.OSMGeoAdmin)
|
||||
site.register(CityMercator, admin.OSMGeoAdmin)
|
||||
|
|
|
@ -1,15 +1,11 @@
|
|||
from __future__ import unicode_literals
|
||||
|
||||
from unittest import skipUnless
|
||||
|
||||
from django.contrib.gis import admin
|
||||
from django.contrib.gis.gdal import HAS_GDAL
|
||||
from django.contrib.gis.geos import Point
|
||||
from django.core.exceptions import ImproperlyConfigured
|
||||
from django.test import TestCase, mock, override_settings, skipUnlessDBFeature
|
||||
from django.test import TestCase, override_settings, skipUnlessDBFeature
|
||||
|
||||
from .admin import UnmodifiableAdmin
|
||||
from .models import City, CityMercator, site
|
||||
from .models import City, site
|
||||
|
||||
|
||||
@skipUnlessDBFeature("gis_enabled")
|
||||
|
@ -56,22 +52,6 @@ class GeoAdminTest(TestCase):
|
|||
""""http://vmap0.tiles.osgeo.org/wms/vmap0", {layers: 'basic', format: 'image/jpeg'});""",
|
||||
result)
|
||||
|
||||
@mock.patch('django.contrib.gis.admin.options.HAS_GDAL', False)
|
||||
def test_no_gdal_admin_model_diffent_srid(self):
|
||||
msg = (
|
||||
'Map SRID is 3857 and SRID of `geoadmin.City.point` is 4326. '
|
||||
'GDAL must be installed to perform the transformation.'
|
||||
)
|
||||
with self.assertRaisesMessage(ImproperlyConfigured, msg):
|
||||
geoadmin = site._registry[City]
|
||||
geoadmin.get_changelist_form(None)()
|
||||
|
||||
@mock.patch('django.contrib.gis.admin.options.HAS_GDAL', False)
|
||||
def test_no_gdal_admin_model_same_srid(self):
|
||||
geoadmin = site._registry[CityMercator]
|
||||
geoadmin.get_changelist_form(None)()
|
||||
|
||||
@skipUnless(HAS_GDAL, "GDAL is required.")
|
||||
def test_olwidget_has_changed(self):
|
||||
"""
|
||||
Check that changes are accurately noticed by OpenLayersWidget.
|
||||
|
|
|
@ -4,8 +4,7 @@ import json
|
|||
|
||||
from django.contrib.gis.geos import LinearRing, Point, Polygon
|
||||
from django.core import serializers
|
||||
from django.test import TestCase, mock, skipUnlessDBFeature
|
||||
from django.utils import six
|
||||
from django.test import TestCase, skipUnlessDBFeature
|
||||
|
||||
from .models import City, MultiFields, PennsylvaniaCity
|
||||
|
||||
|
@ -89,14 +88,6 @@ class GeoJSONSerializerTests(TestCase):
|
|||
[1564802, 5613214]
|
||||
)
|
||||
|
||||
@mock.patch('django.contrib.gis.serializers.geojson.HAS_GDAL', False)
|
||||
def test_without_gdal(self):
|
||||
# Without coordinate transformation, the serialization should succeed:
|
||||
serializers.serialize('geojson', City.objects.all())
|
||||
with six.assertRaisesRegex(self, serializers.base.SerializationError, '.*GDAL is not installed'):
|
||||
# Coordinate transformations need GDAL
|
||||
serializers.serialize('geojson', City.objects.all(), srid=2847)
|
||||
|
||||
def test_deserialization_exception(self):
|
||||
"""
|
||||
GeoJSON cannot be deserialized.
|
||||
|
|
|
@ -8,7 +8,6 @@ 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
|
||||
|
@ -70,7 +69,6 @@ class GeographyTest(TestCase):
|
|||
with self.assertRaises(ValueError):
|
||||
City.objects.get(point__exact=htown.point)
|
||||
|
||||
@skipUnless(HAS_GDAL, "GDAL is required.")
|
||||
def test05_geography_layermapping(self):
|
||||
"Testing LayerMapping support on models with geography fields."
|
||||
# There is a similar test in `layermap` that uses the same data set,
|
||||
|
|
|
@ -1092,19 +1092,6 @@ class GEOSTest(SimpleTestCase, TestDataMixin):
|
|||
self.assertEqual(g1.srid, 4326)
|
||||
self.assertIsNot(g1, g, "Clone didn't happen")
|
||||
|
||||
with mock.patch('django.contrib.gis.gdal.HAS_GDAL', False):
|
||||
g = GEOSGeometry('POINT (-104.609 38.255)', 4326)
|
||||
gt = g.tuple
|
||||
g.transform(4326)
|
||||
self.assertEqual(g.tuple, gt)
|
||||
self.assertEqual(g.srid, 4326)
|
||||
|
||||
g = GEOSGeometry('POINT (-104.609 38.255)', 4326)
|
||||
g1 = g.transform(4326, clone=True)
|
||||
self.assertEqual(g1.tuple, g.tuple)
|
||||
self.assertEqual(g1.srid, 4326)
|
||||
self.assertIsNot(g1, g, "Clone didn't happen")
|
||||
|
||||
@skipUnless(HAS_GDAL, "GDAL is required.")
|
||||
def test_transform_nosrid(self):
|
||||
""" Testing `transform` method (no SRID or negative SRID) """
|
||||
|
@ -1125,17 +1112,6 @@ class GEOSTest(SimpleTestCase, TestDataMixin):
|
|||
with self.assertRaises(GEOSException):
|
||||
g.transform(2774, clone=True)
|
||||
|
||||
@mock.patch('django.contrib.gis.gdal.HAS_GDAL', False)
|
||||
def test_transform_nogdal(self):
|
||||
""" Testing `transform` method (GDAL not available) """
|
||||
g = GEOSGeometry('POINT (-104.609 38.255)', 4326)
|
||||
with self.assertRaises(GEOSException):
|
||||
g.transform(2774)
|
||||
|
||||
g = GEOSGeometry('POINT (-104.609 38.255)', 4326)
|
||||
with self.assertRaises(GEOSException):
|
||||
g.transform(2774, clone=True)
|
||||
|
||||
def test_extent(self):
|
||||
"Testing `extent` method."
|
||||
# The xmin, ymin, xmax, ymax of the MultiPoint should be returned.
|
||||
|
|
|
@ -1,9 +1,6 @@
|
|||
from __future__ import unicode_literals
|
||||
|
||||
from unittest import skipUnless
|
||||
|
||||
from django.contrib.gis.db.models import fields
|
||||
from django.contrib.gis.gdal import HAS_GDAL
|
||||
from django.core.exceptions import ImproperlyConfigured
|
||||
from django.db import connection, migrations, models
|
||||
from django.db.migrations.migration import Migration
|
||||
|
@ -117,7 +114,6 @@ class OperationTests(TransactionTestCase):
|
|||
self.assertSpatialIndexExists('gis_neighborhood', 'heatmap')
|
||||
|
||||
@skipIfDBFeature('supports_raster')
|
||||
@skipUnless(HAS_GDAL, 'A different error is raised if GDAL is not installed.')
|
||||
def test_create_raster_model_on_db_without_raster_support(self):
|
||||
"""
|
||||
Test creating a model with a raster field on a db without raster support.
|
||||
|
@ -127,7 +123,6 @@ class OperationTests(TransactionTestCase):
|
|||
self.set_up_test_model(True)
|
||||
|
||||
@skipIfDBFeature('supports_raster')
|
||||
@skipUnless(HAS_GDAL, 'A different error is raised if GDAL is not installed.')
|
||||
def test_add_raster_field_on_db_without_raster_support(self):
|
||||
"""
|
||||
Test adding a raster field on a db without raster support.
|
||||
|
|
|
@ -2,7 +2,6 @@ from __future__ import unicode_literals
|
|||
|
||||
import os
|
||||
import re
|
||||
from unittest import skipUnless
|
||||
|
||||
from django.contrib.gis.gdal import HAS_GDAL
|
||||
from django.core.management import call_command
|
||||
|
@ -20,9 +19,8 @@ if HAS_GDAL:
|
|||
from .models import AllOGRFields
|
||||
|
||||
|
||||
@skipUnless(HAS_GDAL, "InspectDbTests needs GDAL support")
|
||||
@skipUnlessDBFeature("gis_enabled")
|
||||
class InspectDbTests(TestCase):
|
||||
@skipUnlessDBFeature("gis_enabled")
|
||||
def test_geom_columns(self):
|
||||
"""
|
||||
Test the geo-enabled inspectdb command.
|
||||
|
@ -60,7 +58,7 @@ class InspectDbTests(TestCase):
|
|||
self.assertIn('poly = models.GeometryField(', output)
|
||||
|
||||
|
||||
@skipUnless(HAS_GDAL, "OGRInspectTest needs GDAL support")
|
||||
@skipUnlessDBFeature("gis_enabled")
|
||||
@modify_settings(
|
||||
INSTALLED_APPS={'append': 'django.contrib.gis'},
|
||||
)
|
||||
|
|
|
@ -5,7 +5,6 @@ import os
|
|||
import unittest
|
||||
from copy import copy
|
||||
from decimal import Decimal
|
||||
from unittest import skipUnless
|
||||
|
||||
from django.conf import settings
|
||||
from django.contrib.gis.gdal import HAS_GDAL
|
||||
|
@ -39,7 +38,6 @@ NUMS = [1, 2, 1, 19, 1] # Number of polygons for each.
|
|||
STATES = ['Texas', 'Texas', 'Texas', 'Hawaii', 'Colorado']
|
||||
|
||||
|
||||
@skipUnless(HAS_GDAL, "LayerMapTest needs GDAL support")
|
||||
@skipUnlessDBFeature("gis_enabled")
|
||||
class LayerMapTest(TestCase):
|
||||
|
||||
|
@ -337,7 +335,6 @@ class OtherRouter(object):
|
|||
return True
|
||||
|
||||
|
||||
@skipUnless(HAS_GDAL, "LayerMapRouterTest needs GDAL support")
|
||||
@skipUnlessDBFeature("gis_enabled")
|
||||
@override_settings(DATABASE_ROUTERS=[OtherRouter()])
|
||||
class LayerMapRouterTest(TestCase):
|
||||
|
|
|
@ -1,23 +1,24 @@
|
|||
from django.contrib.gis.gdal import HAS_GDAL
|
||||
|
||||
from ..models import models
|
||||
|
||||
if HAS_GDAL:
|
||||
class RasterModel(models.Model):
|
||||
rast = models.RasterField('A Verbose Raster Name', null=True, srid=4326, spatial_index=True, blank=True)
|
||||
rastprojected = models.RasterField('A Projected Raster Table', srid=3086, null=True)
|
||||
geom = models.PointField(null=True)
|
||||
|
||||
class RasterModel(models.Model):
|
||||
rast = models.RasterField('A Verbose Raster Name', null=True, srid=4326, spatial_index=True, blank=True)
|
||||
rastprojected = models.RasterField('A Projected Raster Table', srid=3086, null=True)
|
||||
geom = models.PointField(null=True)
|
||||
class Meta:
|
||||
required_db_features = ['supports_raster']
|
||||
|
||||
class Meta:
|
||||
required_db_features = ['supports_raster']
|
||||
def __str__(self):
|
||||
return str(self.id)
|
||||
|
||||
def __str__(self):
|
||||
return str(self.id)
|
||||
class RasterRelatedModel(models.Model):
|
||||
rastermodel = models.ForeignKey(RasterModel, models.CASCADE)
|
||||
|
||||
class Meta:
|
||||
required_db_features = ['supports_raster']
|
||||
|
||||
class RasterRelatedModel(models.Model):
|
||||
rastermodel = models.ForeignKey(RasterModel, models.CASCADE)
|
||||
|
||||
class Meta:
|
||||
required_db_features = ['supports_raster']
|
||||
|
||||
def __str__(self):
|
||||
return str(self.id)
|
||||
def __str__(self):
|
||||
return str(self.id)
|
||||
|
|
|
@ -7,18 +7,14 @@ from django.contrib.gis.gdal import HAS_GDAL
|
|||
from django.contrib.gis.geos import GEOSGeometry
|
||||
from django.contrib.gis.measure import D
|
||||
from django.contrib.gis.shortcuts import numpy
|
||||
from django.core.exceptions import ImproperlyConfigured
|
||||
from django.db.models import Q
|
||||
from django.test import (
|
||||
TestCase, TransactionTestCase, mock, skipUnlessDBFeature,
|
||||
)
|
||||
from django.test import TransactionTestCase, skipUnlessDBFeature
|
||||
|
||||
from ..data.rasters.textrasters import JSON_RASTER
|
||||
from ..models import models
|
||||
from .models import RasterModel, RasterRelatedModel
|
||||
|
||||
if HAS_GDAL:
|
||||
from django.contrib.gis.gdal import GDALRaster
|
||||
from .models import RasterModel, RasterRelatedModel
|
||||
|
||||
|
||||
@skipUnlessDBFeature('supports_raster')
|
||||
|
@ -330,12 +326,3 @@ class RasterFieldTest(TransactionTestCase):
|
|||
msg = "Couldn't create spatial object from lookup value '%s'." % obj
|
||||
with self.assertRaisesMessage(ValueError, msg):
|
||||
RasterModel.objects.filter(geom__intersects=obj)
|
||||
|
||||
|
||||
@mock.patch('django.contrib.gis.db.models.fields.HAS_GDAL', False)
|
||||
class RasterFieldWithoutGDALTest(TestCase):
|
||||
|
||||
def test_raster_field_without_gdal_exception(self):
|
||||
msg = 'RasterField requires GDAL.'
|
||||
with self.assertRaisesMessage(ImproperlyConfigured, msg):
|
||||
models.OriginalRasterField()
|
||||
|
|
|
@ -1,14 +1,10 @@
|
|||
from unittest import skipUnless
|
||||
|
||||
from django.contrib.gis import forms
|
||||
from django.contrib.gis.gdal import HAS_GDAL
|
||||
from django.contrib.gis.geos import GEOSGeometry
|
||||
from django.forms import ValidationError
|
||||
from django.test import SimpleTestCase, override_settings, skipUnlessDBFeature
|
||||
from django.utils.html import escape
|
||||
|
||||
|
||||
@skipUnless(HAS_GDAL, "GeometryFieldTest needs GDAL support")
|
||||
@skipUnlessDBFeature("gis_enabled")
|
||||
class GeometryFieldTest(SimpleTestCase):
|
||||
|
||||
|
@ -89,7 +85,6 @@ class GeometryFieldTest(SimpleTestCase):
|
|||
self.assertFalse(form.has_changed())
|
||||
|
||||
|
||||
@skipUnless(HAS_GDAL, "SpecializedFieldTest needs GDAL support")
|
||||
@skipUnlessDBFeature("gis_enabled")
|
||||
class SpecializedFieldTest(SimpleTestCase):
|
||||
def setUp(self):
|
||||
|
@ -260,7 +255,6 @@ class SpecializedFieldTest(SimpleTestCase):
|
|||
self.assertFalse(GeometryForm(data={'g': invalid.wkt}).is_valid())
|
||||
|
||||
|
||||
@skipUnless(HAS_GDAL, "OSMWidgetTest needs GDAL support")
|
||||
@skipUnlessDBFeature("gis_enabled")
|
||||
class OSMWidgetTest(SimpleTestCase):
|
||||
def setUp(self):
|
||||
|
@ -302,7 +296,6 @@ class OSMWidgetTest(SimpleTestCase):
|
|||
rendered)
|
||||
|
||||
|
||||
@skipUnless(HAS_GDAL, "CustomGeometryWidgetTest needs GDAL support")
|
||||
@skipUnlessDBFeature("gis_enabled")
|
||||
class CustomGeometryWidgetTest(SimpleTestCase):
|
||||
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
import re
|
||||
import unittest
|
||||
|
||||
from django.contrib.gis.gdal import HAS_GDAL
|
||||
from django.test import mock, skipUnlessDBFeature
|
||||
from django.test import skipUnlessDBFeature
|
||||
from django.utils import six
|
||||
|
||||
from .utils import SpatialRefSys, oracle, postgis, spatialite
|
||||
|
@ -51,7 +50,6 @@ test_srs = ({
|
|||
})
|
||||
|
||||
|
||||
@unittest.skipUnless(HAS_GDAL, "SpatialRefSysTest needs gdal support")
|
||||
@skipUnlessDBFeature("has_spatialrefsys_table")
|
||||
class SpatialRefSysTest(unittest.TestCase):
|
||||
|
||||
|
@ -61,13 +59,6 @@ class SpatialRefSysTest(unittest.TestCase):
|
|||
self.assertEqual(unit_name, 'degree')
|
||||
self.assertAlmostEqual(unit, 0.01745329251994328)
|
||||
|
||||
@mock.patch('django.contrib.gis.gdal.HAS_GDAL', False)
|
||||
def test_get_units_without_gdal(self):
|
||||
epsg_4326 = next(f for f in test_srs if f['srid'] == 4326)
|
||||
unit, unit_name = SpatialRefSys().get_units(epsg_4326['wkt'])
|
||||
self.assertEqual(unit_name, 'degree')
|
||||
self.assertAlmostEqual(unit, 0.01745329251994328)
|
||||
|
||||
def test_retrieve(self):
|
||||
"""
|
||||
Test retrieval of SpatialRefSys model objects.
|
||||
|
|
Loading…
Reference in New Issue