mirror of
https://github.com/django/django.git
synced 2024-12-22 17:16:24 +00:00
Fixed #30049 -- Initialized GIS widgets when admin inlines are added.
This commit is contained in:
parent
a57596e443
commit
a02b4ce19f
@ -231,3 +231,29 @@ class MapWidget {
|
|||||||
document.getElementById(this.options.id).value = jsonFormat.writeGeometry(geometry);
|
document.getElementById(this.options.id).value = jsonFormat.writeGeometry(geometry);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
function initMapWidgetAfterInlineAdd(event) {
|
||||||
|
const formsetIndex = event.srcElement.id.split('-').pop();
|
||||||
|
event.target.querySelectorAll(".dj_map_wrapper").forEach((wrapper) => {
|
||||||
|
wrapper.querySelector(".dj_map").innerHTML = "";
|
||||||
|
const options = window[wrapper.dataset.widgetoptions];
|
||||||
|
const newOptions = {};
|
||||||
|
for (const key in options) {
|
||||||
|
if (options[key].includes && options[key].includes("__prefix__")) {
|
||||||
|
newOptions[key] = options[key].replace( "__prefix__", formsetIndex);
|
||||||
|
} else {
|
||||||
|
newOptions[key] = options[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
new MapWidget(newOptions);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
document.addEventListener("DOMContentLoaded", () => {
|
||||||
|
document.querySelectorAll(".dj_map_wrapper").forEach((wrapper) => {
|
||||||
|
const options = window[wrapper.dataset.widgetoptions];
|
||||||
|
new MapWidget(options);
|
||||||
|
});
|
||||||
|
document.addEventListener('formset:added', initMapWidgetAfterInlineAdd);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{% load i18n l10n %}
|
{% load i18n l10n %}
|
||||||
|
|
||||||
<div id="{{ id }}_div_map" class="dj_map_wrapper">
|
<div id="{{ id }}_div_map" class="dj_map_wrapper" data-widgetoptions="{{ module }}Options">
|
||||||
<div id="{{ id }}_map" class="dj_map"></div>
|
<div id="{{ id }}_map" class="dj_map"></div>
|
||||||
{% if not disabled %}<span class="clear_features"><a href="">{% translate "Delete all Features" %}</a></span>{% endif %}
|
{% if not disabled %}<span class="clear_features"><a href="">{% translate "Delete all Features" %}</a></span>{% endif %}
|
||||||
{% if display_raw %}<p>{% translate "Debugging window (serialized value)" %}</p>{% endif %}
|
{% if display_raw %}<p>{% translate "Debugging window (serialized value)" %}</p>{% endif %}
|
||||||
@ -27,6 +27,6 @@
|
|||||||
name: '{{ name }}'
|
name: '{{ name }}'
|
||||||
};
|
};
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
var {{ module }} = new MapWidget(options);
|
window.{{ module }}Options = options;
|
||||||
</script>
|
</script>
|
||||||
</div>
|
</div>
|
||||||
|
@ -3,8 +3,19 @@ from django.contrib.gis.db import models
|
|||||||
from ..admin import admin
|
from ..admin import admin
|
||||||
|
|
||||||
|
|
||||||
|
class Country(models.Model):
|
||||||
|
name = models.CharField(max_length=30)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
app_label = "geoadmin"
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.name
|
||||||
|
|
||||||
|
|
||||||
class City(models.Model):
|
class City(models.Model):
|
||||||
name = models.CharField(max_length=30)
|
name = models.CharField(max_length=30)
|
||||||
|
country = models.ForeignKey(Country, on_delete=models.CASCADE)
|
||||||
point = models.PointField()
|
point = models.PointField()
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
@ -23,11 +34,20 @@ class CityAdminCustomWidgetKwargs(admin.GISModelAdmin):
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class CityInline(admin.TabularInline):
|
||||||
|
model = City
|
||||||
|
|
||||||
|
|
||||||
|
class CountryAdmin(admin.ModelAdmin):
|
||||||
|
inlines = [CityInline]
|
||||||
|
|
||||||
|
|
||||||
site = admin.AdminSite(name="gis_admin_modeladmin")
|
site = admin.AdminSite(name="gis_admin_modeladmin")
|
||||||
site.register(City, admin.ModelAdmin)
|
site.register(City, admin.ModelAdmin)
|
||||||
|
|
||||||
site_gis = admin.AdminSite(name="gis_admin_gismodeladmin")
|
site_gis = admin.AdminSite(name="gis_admin_gismodeladmin")
|
||||||
site_gis.register(City, admin.GISModelAdmin)
|
site_gis.register(City, admin.GISModelAdmin)
|
||||||
|
site_gis.register(Country, CountryAdmin)
|
||||||
|
|
||||||
site_gis_custom = admin.AdminSite(name="gis_admin_gismodeladmin")
|
site_gis_custom = admin.AdminSite(name="gis_admin_gismodeladmin")
|
||||||
site_gis_custom.register(City, CityAdminCustomWidgetKwargs)
|
site_gis_custom.register(City, CityAdminCustomWidgetKwargs)
|
||||||
|
@ -1,16 +1,31 @@
|
|||||||
|
from django.contrib.admin.tests import AdminSeleniumTestCase
|
||||||
|
from django.contrib.auth.models import User
|
||||||
from django.contrib.gis.geos import Point
|
from django.contrib.gis.geos import Point
|
||||||
from django.test import SimpleTestCase, override_settings
|
from django.test import TestCase, modify_settings, override_settings
|
||||||
|
from django.test.client import RequestFactory
|
||||||
|
from django.urls import reverse
|
||||||
|
|
||||||
from .models import City, site, site_gis, site_gis_custom
|
from .models import City, site, site_gis, site_gis_custom
|
||||||
|
|
||||||
|
|
||||||
@override_settings(ROOT_URLCONF="django.contrib.gis.tests.geoadmin.urls")
|
@override_settings(
|
||||||
class GeoAdminTest(SimpleTestCase):
|
ROOT_URLCONF="django.contrib.gis.tests.geoadmin.urls",
|
||||||
|
PASSWORD_HASHERS=["django.contrib.auth.hashers.MD5PasswordHasher"],
|
||||||
|
)
|
||||||
|
class GeoAdminTest(TestCase):
|
||||||
admin_site = site # ModelAdmin
|
admin_site = site # ModelAdmin
|
||||||
|
factory = RequestFactory()
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
user = User.objects.create_superuser(
|
||||||
|
username="super", password="secret", email="super@example.com"
|
||||||
|
)
|
||||||
|
self.request = self.factory.get("/admin")
|
||||||
|
self.request.user = user
|
||||||
|
|
||||||
def test_widget_empty_string(self):
|
def test_widget_empty_string(self):
|
||||||
geoadmin = self.admin_site.get_model_admin(City)
|
geoadmin = self.admin_site.get_model_admin(City)
|
||||||
form = geoadmin.get_changelist_form(None)({"point": ""})
|
form = geoadmin.get_changelist_form(self.request)({"point": ""})
|
||||||
with self.assertRaisesMessage(AssertionError, "no logs"):
|
with self.assertRaisesMessage(AssertionError, "no logs"):
|
||||||
with self.assertLogs("django.contrib.gis", "ERROR"):
|
with self.assertLogs("django.contrib.gis", "ERROR"):
|
||||||
output = str(form["point"])
|
output = str(form["point"])
|
||||||
@ -22,7 +37,7 @@ class GeoAdminTest(SimpleTestCase):
|
|||||||
|
|
||||||
def test_widget_invalid_string(self):
|
def test_widget_invalid_string(self):
|
||||||
geoadmin = self.admin_site.get_model_admin(City)
|
geoadmin = self.admin_site.get_model_admin(City)
|
||||||
form = geoadmin.get_changelist_form(None)({"point": "INVALID()"})
|
form = geoadmin.get_changelist_form(self.request)({"point": "INVALID()"})
|
||||||
with self.assertLogs("django.contrib.gis", "ERROR") as cm:
|
with self.assertLogs("django.contrib.gis", "ERROR") as cm:
|
||||||
output = str(form["point"])
|
output = str(form["point"])
|
||||||
self.assertInHTML(
|
self.assertInHTML(
|
||||||
@ -39,7 +54,7 @@ class GeoAdminTest(SimpleTestCase):
|
|||||||
|
|
||||||
def test_widget_has_changed(self):
|
def test_widget_has_changed(self):
|
||||||
geoadmin = self.admin_site.get_model_admin(City)
|
geoadmin = self.admin_site.get_model_admin(City)
|
||||||
form = geoadmin.get_changelist_form(None)()
|
form = geoadmin.get_changelist_form(self.request)()
|
||||||
has_changed = form.fields["point"].has_changed
|
has_changed = form.fields["point"].has_changed
|
||||||
|
|
||||||
initial = Point(13.4197458572965953, 52.5194108501149799, srid=4326)
|
initial = Point(13.4197458572965953, 52.5194108501149799, srid=4326)
|
||||||
@ -60,7 +75,7 @@ class GISAdminTests(GeoAdminTest):
|
|||||||
|
|
||||||
def test_default_gis_widget_kwargs(self):
|
def test_default_gis_widget_kwargs(self):
|
||||||
geoadmin = self.admin_site.get_model_admin(City)
|
geoadmin = self.admin_site.get_model_admin(City)
|
||||||
form = geoadmin.get_changelist_form(None)()
|
form = geoadmin.get_changelist_form(self.request)()
|
||||||
widget = form["point"].field.widget
|
widget = form["point"].field.widget
|
||||||
self.assertEqual(widget.attrs["default_lat"], 47)
|
self.assertEqual(widget.attrs["default_lat"], 47)
|
||||||
self.assertEqual(widget.attrs["default_lon"], 5)
|
self.assertEqual(widget.attrs["default_lon"], 5)
|
||||||
@ -68,8 +83,35 @@ class GISAdminTests(GeoAdminTest):
|
|||||||
|
|
||||||
def test_custom_gis_widget_kwargs(self):
|
def test_custom_gis_widget_kwargs(self):
|
||||||
geoadmin = site_gis_custom.get_model_admin(City)
|
geoadmin = site_gis_custom.get_model_admin(City)
|
||||||
form = geoadmin.get_changelist_form(None)()
|
form = geoadmin.get_changelist_form(self.request)()
|
||||||
widget = form["point"].field.widget
|
widget = form["point"].field.widget
|
||||||
self.assertEqual(widget.attrs["default_lat"], 55)
|
self.assertEqual(widget.attrs["default_lat"], 55)
|
||||||
self.assertEqual(widget.attrs["default_lon"], 37)
|
self.assertEqual(widget.attrs["default_lon"], 37)
|
||||||
self.assertEqual(widget.attrs["default_zoom"], 12)
|
self.assertEqual(widget.attrs["default_zoom"], 12)
|
||||||
|
|
||||||
|
|
||||||
|
@override_settings(ROOT_URLCONF="gis_tests.geoadmin.urls")
|
||||||
|
# GeoDjango admin not yet CSP-compatible with strict values (#25706)
|
||||||
|
@modify_settings(MIDDLEWARE={"remove": "django.contrib.admin.tests.CSPMiddleware"})
|
||||||
|
class GISSeleniumAdminTests(AdminSeleniumTestCase):
|
||||||
|
available_apps = AdminSeleniumTestCase.available_apps + [
|
||||||
|
"django.contrib.gis",
|
||||||
|
"gis_tests.geoadmin",
|
||||||
|
]
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
User.objects.create_superuser(
|
||||||
|
username="super", password="secret", email="super@example.com"
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_gis_widget_initalized_when_inline_added(self):
|
||||||
|
from selenium.webdriver.common.by import By
|
||||||
|
|
||||||
|
self.admin_login(username="super", password="secret")
|
||||||
|
self.selenium.get(self.live_server_url + reverse("admin:geoadmin_country_add"))
|
||||||
|
self.assertCountSeleniumElements("tr.dynamic-city_set", 3)
|
||||||
|
add_button = self.selenium.find_element(By.LINK_TEXT, "Add another City")
|
||||||
|
add_button.click()
|
||||||
|
self.assertCountSeleniumElements("tr.dynamic-city_set", 4)
|
||||||
|
map_div = self.selenium.find_element(By.ID, "id_city_set-3-point_map")
|
||||||
|
self.assertCountSeleniumElements(".ol-layer", 1, root_element=map_div)
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
from django.contrib import admin
|
from django.urls import path
|
||||||
from django.urls import include, path
|
|
||||||
|
from .models import site_gis
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path("admin/", include(admin.site.urls)),
|
path("admin/", site_gis.urls),
|
||||||
]
|
]
|
||||||
|
@ -257,7 +257,8 @@ class SpecializedFieldTest(SimpleTestCase):
|
|||||||
"""
|
"""
|
||||||
self.assertTrue(form_instance.is_valid())
|
self.assertTrue(form_instance.is_valid())
|
||||||
rendered = form_instance.as_p()
|
rendered = form_instance.as_p()
|
||||||
self.assertIn("new MapWidget(options);", rendered)
|
field_name = list(form_instance.fields.keys())[0]
|
||||||
|
self.assertIn(f"window.geodjango_{field_name}Options = options;", rendered)
|
||||||
self.assertIn("map_srid: 3857,", rendered)
|
self.assertIn("map_srid: 3857,", rendered)
|
||||||
self.assertIn("gis/js/OLMapWidget.js", str(form_instance.media))
|
self.assertIn("gis/js/OLMapWidget.js", str(form_instance.media))
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user