summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClaude Paroz <claude@2xlibre.net>2018-02-06 11:51:41 +0100
committerTim Graham <timograham@gmail.com>2018-04-02 10:20:00 -0400
commit2a2ed0e70a93bfd1a3d41af40870fe963dc2687d (patch)
treea23d1526aab1324798e431f78d9327c734a66a92
parent09c6d0146178d83b6bd6cc8bb4162a5ae7c1c5f5 (diff)
Fixed #29116 -- Fixed OpenLayersWidget deserialization ignoring the widget map's SRID.
Regression in 6ecccad711b52f9273b1acb07a57d3f806e93928.
-rw-r--r--django/contrib/gis/forms/fields.py11
-rw-r--r--django/contrib/gis/forms/widgets.py10
-rw-r--r--docs/releases/2.0.4.txt3
-rw-r--r--tests/gis_tests/test_geoforms.py19
4 files changed, 34 insertions, 9 deletions
diff --git a/django/contrib/gis/forms/fields.py b/django/contrib/gis/forms/fields.py
index afb0974415..d05518c971 100644
--- a/django/contrib/gis/forms/fields.py
+++ b/django/contrib/gis/forms/fields.py
@@ -35,9 +35,14 @@ class GeometryField(forms.Field):
return None
if not isinstance(value, GEOSGeometry):
- try:
- value = GEOSGeometry(value)
- except (GEOSException, ValueError, TypeError):
+ if hasattr(self.widget, 'deserialize'):
+ value = self.widget.deserialize(value)
+ else:
+ try:
+ value = GEOSGeometry(value)
+ except (GEOSException, ValueError, TypeError):
+ value = None
+ if value is None:
raise forms.ValidationError(self.error_messages['invalid_geom'], code='invalid_geom')
# Try to set the srid
diff --git a/django/contrib/gis/forms/widgets.py b/django/contrib/gis/forms/widgets.py
index 0ffe2ced77..cd9bff9f68 100644
--- a/django/contrib/gis/forms/widgets.py
+++ b/django/contrib/gis/forms/widgets.py
@@ -2,6 +2,7 @@ import logging
from django.conf import settings
from django.contrib.gis import gdal
+from django.contrib.gis.geometry import json_regex
from django.contrib.gis.geos import GEOSException, GEOSGeometry
from django.forms.widgets import Widget
from django.utils import translation
@@ -36,7 +37,7 @@ class BaseGeometryWidget(Widget):
def deserialize(self, value):
try:
return GEOSGeometry(value)
- except (GEOSException, ValueError) as err:
+ except (GEOSException, ValueError, TypeError) as err:
logger.error("Error creating geometry from value '%s' (%s)", value, err)
return None
@@ -91,6 +92,13 @@ class OpenLayersWidget(BaseGeometryWidget):
def serialize(self, value):
return value.json if value else ''
+ def deserialize(self, value):
+ geom = super().deserialize(value)
+ # GeoJSON assumes WGS84 (4326). Use the map's SRID instead.
+ if geom and json_regex.match(value) and self.map_srid != 4326:
+ geom.srid = self.map_srid
+ return geom
+
class OSMWidget(OpenLayersWidget):
"""
diff --git a/docs/releases/2.0.4.txt b/docs/releases/2.0.4.txt
index 08bd05eb4b..ea1208562d 100644
--- a/docs/releases/2.0.4.txt
+++ b/docs/releases/2.0.4.txt
@@ -29,3 +29,6 @@ Bugfixes
* Fixed a regression in Django 1.11 where an empty choice could be initially
selected for the ``SelectMultiple`` and ``CheckboxSelectMultiple`` widgets
(:ticket:`29273`).
+
+* Fixed a regression in Django 2.0 where ``OpenLayersWidget`` deserialization
+ ignored the widget map's SRID and assumed 4326 (WGS84) (:ticket:`29116`).
diff --git a/tests/gis_tests/test_geoforms.py b/tests/gis_tests/test_geoforms.py
index cdcbe47685..1c221f10bc 100644
--- a/tests/gis_tests/test_geoforms.py
+++ b/tests/gis_tests/test_geoforms.py
@@ -1,7 +1,7 @@
import re
from django.contrib.gis import forms
-from django.contrib.gis.forms import BaseGeometryWidget
+from django.contrib.gis.forms import BaseGeometryWidget, OpenLayersWidget
from django.contrib.gis.geos import GEOSGeometry
from django.forms import ValidationError
from django.test import SimpleTestCase, override_settings
@@ -31,8 +31,9 @@ class GeometryFieldTest(SimpleTestCase):
fld = forms.GeometryField(srid=32140)
tol = 0.0000001
xform_geom = GEOSGeometry('POINT (951640.547328465 4219369.26171664)', srid=32140)
- # The cleaned geometry should be transformed to 32140.
- cleaned_geom = fld.clean('SRID=4326;POINT (-95.363151 29.763374)')
+ # The cleaned geometry is transformed to 32140 (the widget map_srid is 3857).
+ cleaned_geom = fld.clean('SRID=3857;POINT (-10615777.40976205 3473169.895707852)')
+ self.assertEqual(cleaned_geom.srid, 32140)
self.assertTrue(xform_geom.equals_exact(cleaned_geom, tol))
def test_null(self):
@@ -83,6 +84,11 @@ class GeometryFieldTest(SimpleTestCase):
with self.assertRaises(forms.ValidationError):
fld.to_python(wkt)
+ def test_to_python_different_map_srid(self):
+ f = forms.GeometryField(widget=OpenLayersWidget)
+ json = '{ "type": "Point", "coordinates": [ 5.0, 23.0 ] }'
+ self.assertEqual(GEOSGeometry('POINT(5 23)', srid=f.widget.map_srid), f.to_python(json))
+
def test_field_with_text_widget(self):
class PointForm(forms.Form):
pt = forms.PointField(srid=4326, widget=forms.TextInput)
@@ -91,6 +97,8 @@ class GeometryFieldTest(SimpleTestCase):
cleaned_pt = form.fields['pt'].clean('POINT(5 23)')
self.assertEqual(cleaned_pt, GEOSGeometry('POINT(5 23)', srid=4326))
self.assertEqual(4326, cleaned_pt.srid)
+ with self.assertRaisesMessage(ValidationError, 'Invalid geometry value.'):
+ form.fields['pt'].clean('POINT(5)')
point = GEOSGeometry('SRID=4326;POINT(5 23)')
form = PointForm(data={'pt': 'POINT(5 23)'}, initial={'pt': point})
@@ -132,8 +140,9 @@ class GeometryFieldTest(SimpleTestCase):
' rows="10" name="pt3"></textarea>',
output
)
- # Only the invalid PNT(0) should trigger an error log entry
- self.assertEqual(len(logger_calls), 1)
+ # Only the invalid PNT(0) triggers an error log entry.
+ # Deserialization is called in form clean and in widget rendering.
+ self.assertEqual(len(logger_calls), 2)
self.assertEqual(
logger_calls[0],
"Error creating geometry from value 'PNT(0)' (String input "