summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--django/contrib/gis/geos/collections.py14
-rw-r--r--django/contrib/gis/geos/geometry.py8
-rw-r--r--django/contrib/gis/serializers/geojson.py16
-rw-r--r--docs/ref/contrib/gis/serializers.txt14
-rw-r--r--tests/gis_tests/geoapp/test_serializers.py11
5 files changed, 47 insertions, 16 deletions
diff --git a/django/contrib/gis/geos/collections.py b/django/contrib/gis/geos/collections.py
index 32176673c1..4649a895a0 100644
--- a/django/contrib/gis/geos/collections.py
+++ b/django/contrib/gis/geos/collections.py
@@ -2,6 +2,7 @@
This module houses the Geometry Collection objects:
GeometryCollection, MultiPoint, MultiLineString, and MultiPolygon
"""
+import json
from ctypes import byref, c_int, c_uint
from django.contrib.gis.geos import prototypes as capi
@@ -84,6 +85,19 @@ class GeometryCollection(GEOSGeometry):
_assign_extended_slice = GEOSGeometry._assign_extended_slice_rebuild
@property
+ def json(self):
+ if self.__class__.__name__ == 'GeometryCollection':
+ return json.dumps({
+ 'type': self.__class__.__name__,
+ 'geometries': [
+ {'type': geom.__class__.__name__, 'coordinates': geom.coords}
+ for geom in self
+ ],
+ })
+ return super(GeometryCollection, self).json
+ geojson = json
+
+ @property
def kml(self):
"Returns the KML for this Geometry Collection."
return '<MultiGeometry>%s</MultiGeometry>' % ''.join(g.kml for g in self)
diff --git a/django/contrib/gis/geos/geometry.py b/django/contrib/gis/geos/geometry.py
index 4cbd561e3c..61bf590ac5 100644
--- a/django/contrib/gis/geos/geometry.py
+++ b/django/contrib/gis/geos/geometry.py
@@ -4,6 +4,7 @@
"""
from __future__ import unicode_literals
+import json
from ctypes import addressof, byref, c_double
from django.contrib.gis import gdal
@@ -411,12 +412,9 @@ class GEOSGeometry(GEOSBase, ListMixin):
@property
def json(self):
"""
- Returns GeoJSON representation of this Geometry if GDAL is installed.
+ Returns GeoJSON representation of this Geometry.
"""
- if gdal.HAS_GDAL:
- return self.ogr.json
- else:
- raise GEOSException('GeoJSON output only supported when GDAL is installed.')
+ return json.dumps({'type': self.__class__.__name__, 'coordinates': self.coords})
geojson = json
@property
diff --git a/django/contrib/gis/serializers/geojson.py b/django/contrib/gis/serializers/geojson.py
index 9c15b49676..f26147a59a 100644
--- a/django/contrib/gis/serializers/geojson.py
+++ b/django/contrib/gis/serializers/geojson.py
@@ -17,17 +17,14 @@ class Serializer(JSONSerializer):
def _init_options(self):
super(Serializer, self)._init_options()
self.geometry_field = self.json_kwargs.pop('geometry_field', None)
- self.srs = SpatialReference(self.json_kwargs.pop('srid', 4326))
+ self.srid = self.json_kwargs.pop('srid', 4326)
def start_serialization(self):
- if not HAS_GDAL:
- # GDAL is needed for the geometry.geojson call
- raise SerializationError("The geojson serializer requires the GDAL library.")
self._init_options()
self._cts = {} # cache of CoordTransform's
self.stream.write(
'{"type": "FeatureCollection", "crs": {"type": "name", "properties": {"name": "EPSG:%d"}},'
- ' "features": [' % self.srs.srid)
+ ' "features": [' % self.srid)
def end_serialization(self):
self.stream.write(']}')
@@ -48,10 +45,15 @@ class Serializer(JSONSerializer):
"properties": self._current,
}
if self._geometry:
- if self._geometry.srid != self.srs.srid:
+ 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:
- self._cts[self._geometry.srid] = CoordTransform(self._geometry.srs, self.srs)
+ srs = SpatialReference(self.srid)
+ self._cts[self._geometry.srid] = CoordTransform(self._geometry.srs, srs)
self._geometry.transform(self._cts[self._geometry.srid])
data["geometry"] = eval(self._geometry.geojson)
else:
diff --git a/docs/ref/contrib/gis/serializers.txt b/docs/ref/contrib/gis/serializers.txt
index 54b6c5727c..59266940e3 100644
--- a/docs/ref/contrib/gis/serializers.txt
+++ b/docs/ref/contrib/gis/serializers.txt
@@ -7,9 +7,17 @@ GeoJSON Serializer
.. module:: django.contrib.gis.serializers.geojson
:synopsis: Serialization of GeoDjango models in the GeoJSON format.
-GeoDjango provides a specific serializer for the `GeoJSON`__ format. The GDAL
-library is required for this serializer. See :doc:`/topics/serialization` for
-more information on serialization.
+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).
+
+.. versionchanged:: 1.9
+
+ The GeoJSON serializer no longer needs GDAL if all geometries are in the
+ same coordinate system as the ``srid`` serializer option.
__ http://geojson.org/
diff --git a/tests/gis_tests/geoapp/test_serializers.py b/tests/gis_tests/geoapp/test_serializers.py
index 09f837417b..1bf3ec0acf 100644
--- a/tests/gis_tests/geoapp/test_serializers.py
+++ b/tests/gis_tests/geoapp/test_serializers.py
@@ -4,7 +4,8 @@ import json
from django.contrib.gis.geos import LinearRing, Point, Polygon
from django.core import serializers
-from django.test import TestCase, skipUnlessDBFeature
+from django.test import TestCase, mock, skipUnlessDBFeature
+from django.utils import six
from .models import City, MultiFields, PennsylvaniaCity
@@ -70,6 +71,14 @@ class GeoJSONSerializerTests(TestCase):
[int(c) for c in geodata['features'][0]['geometry']['coordinates']],
[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.