1
0
mirror of https://github.com/django/django.git synced 2025-10-26 07:06:08 +00:00

Fixed #25706 -- Refactored geometry widgets to remove inline JavaScript.

Refactored GIS-related JavaScript initialization to eliminate inline
scripts from templates. Added support for specifying a base layer using
the new `base_layer_name` attribute on `BaseGeometryWidget`, allowing
custom map tile providers via user-defined JavaScript.

As a result, the `gis/openlayers-osm.html` template was removed.

Thanks Sarah Boyce for reviews.

Co-authored-by: Natalia <124304+nessita@users.noreply.github.com>
This commit is contained in:
Claude Paroz
2024-08-18 15:29:30 +02:00
committed by nessita
parent e80b33ae4d
commit f2f6046c0f
8 changed files with 308 additions and 96 deletions

View File

@@ -4,6 +4,7 @@ from django.contrib.gis import forms
from django.contrib.gis.forms import BaseGeometryWidget, OpenLayersWidget
from django.contrib.gis.geos import GEOSGeometry
from django.core.exceptions import ValidationError
from django.template.defaultfilters import json_script
from django.test import SimpleTestCase, override_settings
from django.utils.html import escape
@@ -183,6 +184,37 @@ class GeometryFieldTest(SimpleTestCase):
"unrecognized as WKT EWKT, and HEXEWKB.)",
)
def test_override_attrs(self):
self.assertIsNone(forms.BaseGeometryWidget.base_layer)
self.assertEqual(forms.BaseGeometryWidget.geom_type, "GEOMETRY")
self.assertEqual(forms.BaseGeometryWidget.map_srid, 4326)
self.assertIs(forms.BaseGeometryWidget.display_raw, False)
class PointForm(forms.Form):
p = forms.PointField(
widget=forms.OpenLayersWidget(
attrs={
"base_layer": "some-test-file",
"map_srid": 1234,
}
),
)
form = PointForm()
rendered = form.as_p()
attrs = {
"base_layer": "some-test-file",
"geom_type": "POINT",
"map_srid": 1234,
"display_raw": False,
"required": True,
"id": "id_p",
"geom_name": "Point",
}
expected = json_script(attrs, "mapwidget-options")
self.assertInHTML(expected, rendered)
class SpecializedFieldTest(SimpleTestCase):
def setUp(self):
@@ -250,15 +282,29 @@ class SpecializedFieldTest(SimpleTestCase):
),
}
def assertMapWidget(self, form_instance):
def assertMapWidget(self, form_instance, geom_name):
"""
Make sure the MapWidget js is passed in the form media and a MapWidget
is actually created
"""
self.assertTrue(form_instance.is_valid())
rendered = form_instance.as_p()
self.assertIn("new MapWidget(options);", rendered)
self.assertIn("map_srid: 3857,", rendered)
map_fields = [
f for f in form_instance if isinstance(f.field, forms.GeometryField)
]
for map_field in map_fields:
attrs = {
"base_layer": "nasaWorldview",
"geom_type": map_field.field.geom_type,
"map_srid": 3857,
"display_raw": False,
"required": True,
"id": map_field.id_for_label,
"geom_name": geom_name,
}
expected = json_script(attrs, "mapwidget-options")
self.assertInHTML(expected, rendered)
self.assertIn("gis/js/OLMapWidget.js", str(form_instance.media))
def assertTextarea(self, geom, rendered):
@@ -279,7 +325,7 @@ class SpecializedFieldTest(SimpleTestCase):
geom = self.geometries["point"]
form = PointForm(data={"p": geom})
self.assertTextarea(geom, form.as_p())
self.assertMapWidget(form)
self.assertMapWidget(form, "Point")
self.assertFalse(PointForm().is_valid())
invalid = PointForm(data={"p": "some invalid geom"})
self.assertFalse(invalid.is_valid())
@@ -295,7 +341,7 @@ class SpecializedFieldTest(SimpleTestCase):
geom = self.geometries["multipoint"]
form = PointForm(data={"p": geom})
self.assertTextarea(geom, form.as_p())
self.assertMapWidget(form)
self.assertMapWidget(form, "MultiPoint")
self.assertFalse(PointForm().is_valid())
for invalid in [
@@ -310,7 +356,7 @@ class SpecializedFieldTest(SimpleTestCase):
geom = self.geometries["linestring"]
form = LineStringForm(data={"f": geom})
self.assertTextarea(geom, form.as_p())
self.assertMapWidget(form)
self.assertMapWidget(form, "LineString")
self.assertFalse(LineStringForm().is_valid())
for invalid in [
@@ -325,7 +371,7 @@ class SpecializedFieldTest(SimpleTestCase):
geom = self.geometries["multilinestring"]
form = LineStringForm(data={"f": geom})
self.assertTextarea(geom, form.as_p())
self.assertMapWidget(form)
self.assertMapWidget(form, "MultiLineString")
self.assertFalse(LineStringForm().is_valid())
for invalid in [
@@ -340,7 +386,7 @@ class SpecializedFieldTest(SimpleTestCase):
geom = self.geometries["polygon"]
form = PolygonForm(data={"p": geom})
self.assertTextarea(geom, form.as_p())
self.assertMapWidget(form)
self.assertMapWidget(form, "Polygon")
self.assertFalse(PolygonForm().is_valid())
for invalid in [
@@ -355,7 +401,7 @@ class SpecializedFieldTest(SimpleTestCase):
geom = self.geometries["multipolygon"]
form = PolygonForm(data={"p": geom})
self.assertTextarea(geom, form.as_p())
self.assertMapWidget(form)
self.assertMapWidget(form, "MultiPolygon")
self.assertFalse(PolygonForm().is_valid())
for invalid in [
@@ -370,7 +416,7 @@ class SpecializedFieldTest(SimpleTestCase):
geom = self.geometries["geometrycollection"]
form = GeometryForm(data={"g": geom})
self.assertTextarea(geom, form.as_p())
self.assertMapWidget(form)
self.assertMapWidget(form, "GeometryCollection")
self.assertFalse(GeometryForm().is_valid())
for invalid in [
@@ -393,8 +439,8 @@ class OSMWidgetTest(SimpleTestCase):
form = PointForm(data={"p": geom})
rendered = form.as_p()
self.assertIn("ol.source.OSM()", rendered)
self.assertIn("id: 'id_p',", rendered)
self.assertIn('"base_layer": "osm"', rendered)
self.assertIn('<textarea id="id_p"', rendered)
def test_default_lat_lon(self):
self.assertEqual(forms.OSMWidget.default_lon, 5)
@@ -415,9 +461,20 @@ class OSMWidgetTest(SimpleTestCase):
form = PointForm()
rendered = form.as_p()
self.assertIn("options['default_lon'] = 20;", rendered)
self.assertIn("options['default_lat'] = 30;", rendered)
self.assertIn("options['default_zoom'] = 17;", rendered)
attrs = {
"base_layer": "osm",
"geom_type": "POINT",
"map_srid": 3857,
"display_raw": False,
"default_lon": 20,
"default_lat": 30,
"default_zoom": 17,
"required": True,
"id": "id_p",
"geom_name": "Point",
}
expected = json_script(attrs, "mapwidget-options")
self.assertInHTML(expected, rendered)
class GeometryWidgetTests(SimpleTestCase):
@@ -425,15 +482,15 @@ class GeometryWidgetTests(SimpleTestCase):
# The Widget.get_context() attrs argument overrides self.attrs.
widget = BaseGeometryWidget(attrs={"geom_type": "POINT"})
context = widget.get_context("point", None, attrs={"geom_type": "POINT2"})
self.assertEqual(context["geom_type"], "POINT2")
self.assertEqual(context["widget"]["attrs"]["geom_type"], "POINT2")
# Widget.get_context() returns expected name for geom_type.
widget = BaseGeometryWidget(attrs={"geom_type": "POLYGON"})
context = widget.get_context("polygon", None, None)
self.assertEqual(context["geom_type"], "Polygon")
self.assertEqual(context["widget"]["attrs"]["geom_name"], "Polygon")
# Widget.get_context() returns 'Geometry' instead of 'Unknown'.
widget = BaseGeometryWidget(attrs={"geom_type": "GEOMETRY"})
context = widget.get_context("geometry", None, None)
self.assertEqual(context["geom_type"], "Geometry")
self.assertEqual(context["widget"]["attrs"]["geom_name"], "Geometry")
def test_subwidgets(self):
widget = forms.BaseGeometryWidget()
@@ -443,7 +500,10 @@ class GeometryWidgetTests(SimpleTestCase):
{
"is_hidden": False,
"attrs": {
"base_layer": None,
"display_raw": False,
"map_srid": 4326,
"geom_name": "Geometry",
"geom_type": "GEOMETRY",
"display_raw": False,
},