1
0
mirror of https://github.com/django/django.git synced 2025-03-31 19:46:42 +00:00

Fixed #25873 -- Made GEOSGeometry handle the srid parameter more predictably.

This commit is contained in:
Sergey Fedoseev 2017-03-30 18:38:26 +05:00 committed by Tim Graham
parent 068d75688f
commit 6ecccad711
4 changed files with 41 additions and 8 deletions

View File

@ -35,7 +35,7 @@ class BaseGeometryWidget(Widget):
def deserialize(self, value): def deserialize(self, value):
try: try:
return GEOSGeometry(value, self.map_srid) return GEOSGeometry(value)
except (GEOSException, ValueError) as err: except (GEOSException, ValueError) as err:
logger.error("Error creating geometry from value '%s' (%s)", value, err) logger.error("Error creating geometry from value '%s' (%s)", value, err)
return None return None
@ -48,7 +48,7 @@ class BaseGeometryWidget(Widget):
if value: if value:
# Check that srid of value and map match # Check that srid of value and map match
if value.srid != self.map_srid: if value.srid and value.srid != self.map_srid:
try: try:
ogr = value.ogr ogr = value.ogr
ogr.transform(self.map_srid) ogr.transform(self.map_srid)

View File

@ -46,6 +46,7 @@ class GEOSGeometry(GEOSBase, ListMixin):
The `srid` keyword is used to specify the Source Reference Identifier The `srid` keyword is used to specify the Source Reference Identifier
(SRID) number for this Geometry. If not set, the SRID will be None. (SRID) number for this Geometry. If not set, the SRID will be None.
""" """
input_srid = None
if isinstance(geo_input, bytes): if isinstance(geo_input, bytes):
geo_input = force_text(geo_input) geo_input = force_text(geo_input)
if isinstance(geo_input, str): if isinstance(geo_input, str):
@ -53,7 +54,7 @@ class GEOSGeometry(GEOSBase, ListMixin):
if wkt_m: if wkt_m:
# Handling WKT input. # Handling WKT input.
if wkt_m.group('srid'): if wkt_m.group('srid'):
srid = int(wkt_m.group('srid')) input_srid = int(wkt_m.group('srid'))
g = wkt_r().read(force_bytes(wkt_m.group('wkt'))) g = wkt_r().read(force_bytes(wkt_m.group('wkt')))
elif hex_regex.match(geo_input): elif hex_regex.match(geo_input):
# Handling HEXEWKB input. # Handling HEXEWKB input.
@ -75,14 +76,17 @@ class GEOSGeometry(GEOSBase, ListMixin):
# Invalid geometry type. # Invalid geometry type.
raise TypeError('Improper geometry input type: %s' % type(geo_input)) raise TypeError('Improper geometry input type: %s' % type(geo_input))
if g: if not g:
# Setting the pointer object with a valid pointer.
self.ptr = g
else:
raise GEOSException('Could not initialize GEOS Geometry with given input.') raise GEOSException('Could not initialize GEOS Geometry with given input.')
input_srid = input_srid or capi.geos_get_srid(g) or None
if input_srid and srid and input_srid != srid:
raise ValueError('Input geometry already has SRID: %d.' % input_srid)
# Setting the pointer object with a valid pointer.
self.ptr = g
# Post-initialization setup. # Post-initialization setup.
self._post_init(srid) self._post_init(input_srid or srid)
def _post_init(self, srid): def _post_init(self, srid):
"Perform post-initialization setup." "Perform post-initialization setup."

View File

@ -194,6 +194,27 @@ This is the base class for all GEOS geometry objects. It initializes on the
given ``geo_input`` argument, and then assumes the proper geometry subclass given ``geo_input`` argument, and then assumes the proper geometry subclass
(e.g., ``GEOSGeometry('POINT(1 1)')`` will create a :class:`Point` object). (e.g., ``GEOSGeometry('POINT(1 1)')`` will create a :class:`Point` object).
The ``srid`` parameter, if given, is set as the SRID of the created geometry if
``geo_input`` doesn't have an SRID. If different SRIDs are provided through the
``geo_input`` and ``srid`` parameters, ``ValueError`` is raised::
>>> from django.contrib.gis.geos import GEOSGeometry
>>> GEOSGeometry('POINT EMPTY', srid=4326).ewkt
'SRID=4326;POINT EMPTY'
>>> GEOSGeometry('SRID=4326;POINT EMPTY', srid=4326).ewkt
'SRID=4326;POINT EMPTY'
>>> GEOSGeometry('SRID=1;POINT EMPTY', srid=4326)
Traceback (most recent call last):
...
ValueError: Input geometry already has SRID: 1.
.. versionchanged:: 2.0
In older versions, the ``srid`` parameter is handled differently for WKT
and WKB input. For WKT, ``srid`` is used only if the input geometry doesn't
have an SRID. For WKB, ``srid`` (if given) replaces the SRID of the input
geometry.
The following input formats, along with their corresponding Python types, The following input formats, along with their corresponding Python types,
are accepted: are accepted:

View File

@ -708,6 +708,14 @@ class GEOSTest(SimpleTestCase, TestDataMixin):
pnt_wo_srid = Point(1, 1) pnt_wo_srid = Point(1, 1)
pnt_wo_srid.srid = pnt_wo_srid.srid pnt_wo_srid.srid = pnt_wo_srid.srid
# Input geometries that have an SRID.
self.assertEqual(GEOSGeometry(pnt.ewkt, srid=pnt.srid).srid, pnt.srid)
self.assertEqual(GEOSGeometry(pnt.ewkb, srid=pnt.srid).srid, pnt.srid)
with self.assertRaisesMessage(ValueError, 'Input geometry already has SRID: %d.' % pnt.srid):
GEOSGeometry(pnt.ewkt, srid=1)
with self.assertRaisesMessage(ValueError, 'Input geometry already has SRID: %d.' % pnt.srid):
GEOSGeometry(pnt.ewkb, srid=1)
@skipUnless(HAS_GDAL, "GDAL is required.") @skipUnless(HAS_GDAL, "GDAL is required.")
def test_custom_srid(self): def test_custom_srid(self):
"""Test with a null srid and a srid unknown to GDAL.""" """Test with a null srid and a srid unknown to GDAL."""