mirror of
				https://github.com/django/django.git
				synced 2025-10-31 09:41:08 +00:00 
			
		
		
		
	Refs #27674 -- Removed GeoModelAdmin and OSMGeoAdmin per deprecation timeline.
This commit is contained in:
		| @@ -11,7 +11,7 @@ from django.contrib.admin import ( | ||||
|     register, | ||||
|     site, | ||||
| ) | ||||
| from django.contrib.gis.admin.options import GeoModelAdmin, GISModelAdmin, OSMGeoAdmin | ||||
| from django.contrib.gis.admin.options import GISModelAdmin | ||||
| from django.contrib.gis.admin.widgets import OpenLayersWidget | ||||
|  | ||||
| __all__ = [ | ||||
| @@ -28,7 +28,5 @@ __all__ = [ | ||||
|     "site", | ||||
|     "GISModelAdmin", | ||||
|     # RemovedInDjango50Warning. | ||||
|     "GeoModelAdmin", | ||||
|     "OpenLayersWidget", | ||||
|     "OSMGeoAdmin", | ||||
| ] | ||||
|   | ||||
| @@ -1,12 +1,6 @@ | ||||
| import warnings | ||||
|  | ||||
| from django.contrib.admin import ModelAdmin | ||||
| from django.contrib.gis.admin.widgets import OpenLayersWidget | ||||
| from django.contrib.gis.db import models | ||||
| from django.contrib.gis.forms import OSMWidget | ||||
| from django.contrib.gis.gdal import OGRGeomType | ||||
| from django.forms import Media | ||||
| from django.utils.deprecation import RemovedInDjango50Warning | ||||
|  | ||||
|  | ||||
| class GeoModelAdminMixin: | ||||
| @@ -25,156 +19,3 @@ class GeoModelAdminMixin: | ||||
|  | ||||
| class GISModelAdmin(GeoModelAdminMixin, ModelAdmin): | ||||
|     pass | ||||
|  | ||||
|  | ||||
| # RemovedInDjango50Warning. | ||||
| spherical_mercator_srid = 3857 | ||||
|  | ||||
|  | ||||
| # RemovedInDjango50Warning. | ||||
| class GeoModelAdmin(ModelAdmin): | ||||
|     """ | ||||
|     The administration options class for Geographic models. Map settings | ||||
|     may be overloaded from their defaults to create custom maps. | ||||
|     """ | ||||
|  | ||||
|     # The default map settings that may be overloaded -- still subject | ||||
|     # to API changes. | ||||
|     default_lon = 0 | ||||
|     default_lat = 0 | ||||
|     default_zoom = 4 | ||||
|     display_wkt = False | ||||
|     display_srid = False | ||||
|     extra_js = [] | ||||
|     num_zoom = 18 | ||||
|     max_zoom = False | ||||
|     min_zoom = False | ||||
|     units = False | ||||
|     max_resolution = False | ||||
|     max_extent = False | ||||
|     modifiable = True | ||||
|     mouse_position = True | ||||
|     scale_text = True | ||||
|     layerswitcher = True | ||||
|     scrollable = True | ||||
|     map_width = 600 | ||||
|     map_height = 400 | ||||
|     map_srid = 4326 | ||||
|     map_template = "gis/admin/openlayers.html" | ||||
|     openlayers_url = ( | ||||
|         "https://cdnjs.cloudflare.com/ajax/libs/openlayers/2.13.1/OpenLayers.js" | ||||
|     ) | ||||
|     point_zoom = num_zoom - 6 | ||||
|     wms_url = "http://vmap0.tiles.osgeo.org/wms/vmap0" | ||||
|     wms_layer = "basic" | ||||
|     wms_name = "OpenLayers WMS" | ||||
|     wms_options = {"format": "image/jpeg"} | ||||
|     debug = False | ||||
|     widget = OpenLayersWidget | ||||
|  | ||||
|     def __init__(self, *args, **kwargs): | ||||
|         warnings.warn( | ||||
|             "django.contrib.gis.admin.GeoModelAdmin and OSMGeoAdmin are " | ||||
|             "deprecated in favor of django.contrib.admin.ModelAdmin and " | ||||
|             "django.contrib.gis.admin.GISModelAdmin.", | ||||
|             RemovedInDjango50Warning, | ||||
|             stacklevel=2, | ||||
|         ) | ||||
|         super().__init__(*args, **kwargs) | ||||
|  | ||||
|     @property | ||||
|     def media(self): | ||||
|         "Injects OpenLayers JavaScript into the admin." | ||||
|         return super().media + Media(js=[self.openlayers_url] + self.extra_js) | ||||
|  | ||||
|     def formfield_for_dbfield(self, db_field, request, **kwargs): | ||||
|         """ | ||||
|         Overloaded from ModelAdmin so that an OpenLayersWidget is used | ||||
|         for viewing/editing 2D GeometryFields (OpenLayers 2 does not support | ||||
|         3D editing). | ||||
|         """ | ||||
|         if isinstance(db_field, models.GeometryField) and db_field.dim < 3: | ||||
|             # Setting the widget with the newly defined widget. | ||||
|             kwargs["widget"] = self.get_map_widget(db_field) | ||||
|             return db_field.formfield(**kwargs) | ||||
|         else: | ||||
|             return super().formfield_for_dbfield(db_field, request, **kwargs) | ||||
|  | ||||
|     def get_map_widget(self, db_field): | ||||
|         """ | ||||
|         Return a subclass of the OpenLayersWidget (or whatever was specified | ||||
|         in the `widget` attribute) using the settings from the attributes set | ||||
|         in this class. | ||||
|         """ | ||||
|         is_collection = db_field.geom_type in ( | ||||
|             "MULTIPOINT", | ||||
|             "MULTILINESTRING", | ||||
|             "MULTIPOLYGON", | ||||
|             "GEOMETRYCOLLECTION", | ||||
|         ) | ||||
|         if is_collection: | ||||
|             if db_field.geom_type == "GEOMETRYCOLLECTION": | ||||
|                 collection_type = "Any" | ||||
|             else: | ||||
|                 collection_type = OGRGeomType(db_field.geom_type.replace("MULTI", "")) | ||||
|         else: | ||||
|             collection_type = "None" | ||||
|  | ||||
|         class OLMap(self.widget): | ||||
|             template_name = self.map_template | ||||
|             geom_type = db_field.geom_type | ||||
|  | ||||
|             wms_options = "" | ||||
|             if self.wms_options: | ||||
|                 wms_options = ["%s: '%s'" % pair for pair in self.wms_options.items()] | ||||
|                 wms_options = ", %s" % ", ".join(wms_options) | ||||
|  | ||||
|             params = { | ||||
|                 "default_lon": self.default_lon, | ||||
|                 "default_lat": self.default_lat, | ||||
|                 "default_zoom": self.default_zoom, | ||||
|                 "display_wkt": self.debug or self.display_wkt, | ||||
|                 "geom_type": OGRGeomType(db_field.geom_type), | ||||
|                 "field_name": db_field.name, | ||||
|                 "is_collection": is_collection, | ||||
|                 "scrollable": self.scrollable, | ||||
|                 "layerswitcher": self.layerswitcher, | ||||
|                 "collection_type": collection_type, | ||||
|                 "is_generic": db_field.geom_type == "GEOMETRY", | ||||
|                 "is_linestring": db_field.geom_type | ||||
|                 in ("LINESTRING", "MULTILINESTRING"), | ||||
|                 "is_polygon": db_field.geom_type in ("POLYGON", "MULTIPOLYGON"), | ||||
|                 "is_point": db_field.geom_type in ("POINT", "MULTIPOINT"), | ||||
|                 "num_zoom": self.num_zoom, | ||||
|                 "max_zoom": self.max_zoom, | ||||
|                 "min_zoom": self.min_zoom, | ||||
|                 "units": self.units,  # likely should get from object | ||||
|                 "max_resolution": self.max_resolution, | ||||
|                 "max_extent": self.max_extent, | ||||
|                 "modifiable": self.modifiable, | ||||
|                 "mouse_position": self.mouse_position, | ||||
|                 "scale_text": self.scale_text, | ||||
|                 "map_width": self.map_width, | ||||
|                 "map_height": self.map_height, | ||||
|                 "point_zoom": self.point_zoom, | ||||
|                 "srid": self.map_srid, | ||||
|                 "display_srid": self.display_srid, | ||||
|                 "wms_url": self.wms_url, | ||||
|                 "wms_layer": self.wms_layer, | ||||
|                 "wms_name": self.wms_name, | ||||
|                 "wms_options": wms_options, | ||||
|                 "debug": self.debug, | ||||
|             } | ||||
|  | ||||
|         return OLMap | ||||
|  | ||||
|  | ||||
| # RemovedInDjango50Warning. | ||||
| class OSMGeoAdmin(GeoModelAdmin): | ||||
|     map_template = "gis/admin/osm.html" | ||||
|     num_zoom = 20 | ||||
|     map_srid = spherical_mercator_srid | ||||
|     max_extent = "-20037508,-20037508,20037508,20037508" | ||||
|     max_resolution = "156543.0339" | ||||
|     point_zoom = num_zoom - 6 | ||||
|     units = "m" | ||||
|   | ||||
| @@ -1,31 +0,0 @@ | ||||
| {% block extrastyle %} | ||||
| {% load i18n static %}{% get_current_language_bidi as LANGUAGE_BIDI %} | ||||
| <style type="text/css"> | ||||
|   #{{ id }}_map { width: {{ map_width }}px; height: {{ map_height }}px; } | ||||
|   #{{ id }}_map .aligned label { float:inherit; } | ||||
|   #{{ id }}_admin_map { position: relative; vertical-align: top; z-index: 0; float: {{ LANGUAGE_BIDI|yesno:"right,left" }}; } | ||||
|   {% if not display_wkt %}#{{ id }} { display: none; }{% endif %} | ||||
|   .olControlEditingToolbar .olControlModifyFeatureItemActive { | ||||
|      background-image: url("{% static "admin/img/gis/move_vertex_on.svg" %}"); | ||||
|      background-repeat: no-repeat; | ||||
|   } | ||||
|   .olControlEditingToolbar .olControlModifyFeatureItemInactive { | ||||
|      background-image: url("{% static "admin/img/gis/move_vertex_off.svg" %}"); | ||||
|      background-repeat: no-repeat; | ||||
|   } | ||||
| </style> | ||||
| {% endblock %} | ||||
| <span id="{{ id }}_admin_map"> | ||||
| <script> | ||||
| //<![CDATA[ | ||||
| {% block openlayers %}{% include "gis/admin/openlayers.js" %}{% endblock %} | ||||
| //]]> | ||||
| </script> | ||||
| <div id="{{ id }}_map" dir="{{ LANGUAGE_BIDI|yesno:'rtl,ltr,auto' }}"></div> | ||||
| {% if editable %} | ||||
| <a href="javascript:{{ module }}.clearFeatures()">{% translate "Delete all Features" %}</a> | ||||
| {% endif %} | ||||
| {% if display_wkt %}<p>{% translate "WKT debugging window:" %} </p>{% endif %} | ||||
| <textarea id="{{ id }}" class="vWKTField required" cols="150" rows="10" name="{{ name }}">{{ wkt }}</textarea> | ||||
| <script>{% block init_function %}{{ module }}.init();{% endblock %}</script> | ||||
| </span> | ||||
| @@ -1,176 +0,0 @@ | ||||
| {% load l10n %} | ||||
| OpenLayers.Projection.addTransform("EPSG:4326", "EPSG:3857", OpenLayers.Layer.SphericalMercator.projectForward); | ||||
| {% block vars %}var {{ module }} = {}; | ||||
| {{ module }}.map = null; {{ module }}.controls = null; {{ module }}.panel = null; {{ module }}.re = new RegExp("^SRID=\\d+;(.+)", "i"); {{ module }}.layers = {}; | ||||
| {{ module }}.modifiable = {{ modifiable|yesno:"true,false" }}; | ||||
| {{ module }}.wkt_f = new OpenLayers.Format.WKT(); | ||||
| {{ module }}.is_collection = {{ is_collection|yesno:"true,false" }}; | ||||
| {{ module }}.collection_type = '{{ collection_type }}'; | ||||
| {{ module }}.is_generic = {{ is_generic|yesno:"true,false" }}; | ||||
| {{ module }}.is_linestring = {{ is_linestring|yesno:"true,false" }}; | ||||
| {{ module }}.is_polygon = {{ is_polygon|yesno:"true,false" }}; | ||||
| {{ module }}.is_point = {{ is_point|yesno:"true,false" }}; | ||||
| {% endblock %} | ||||
| {{ module }}.get_ewkt = function(feat){ | ||||
|     return 'SRID={{ srid|unlocalize }};' + {{ module }}.wkt_f.write(feat); | ||||
| }; | ||||
| {{ module }}.read_wkt = function(wkt){ | ||||
|     // OpenLayers cannot handle EWKT -- we make sure to strip it out. | ||||
|     // EWKT is only exposed to OL if there's a validation error in the admin. | ||||
|     var match = {{ module }}.re.exec(wkt); | ||||
|     if (match){wkt = match[1];} | ||||
|     return {{ module }}.wkt_f.read(wkt); | ||||
| }; | ||||
| {{ module }}.write_wkt = function(feat){ | ||||
|     if ({{ module }}.is_collection){ {{ module }}.num_geom = feat.geometry.components.length;} | ||||
|     else { {{ module }}.num_geom = 1;} | ||||
|     document.getElementById('{{ id }}').value = {{ module }}.get_ewkt(feat); | ||||
| }; | ||||
| {{ module }}.add_wkt = function(event){ | ||||
|     // This function will sync the contents of the `vector` layer with the | ||||
|     // WKT in the text field. | ||||
|     if ({{ module }}.is_collection){ | ||||
|         var feat = new OpenLayers.Feature.Vector(new OpenLayers.Geometry.{{ geom_type }}()); | ||||
|         for (var i = 0; i < {{ module }}.layers.vector.features.length; i++){ | ||||
|             feat.geometry.addComponents([{{ module }}.layers.vector.features[i].geometry]); | ||||
|         } | ||||
|         {{ module }}.write_wkt(feat); | ||||
|     } else { | ||||
|         // Make sure to remove any previously added features. | ||||
|         if ({{ module }}.layers.vector.features.length > 1){ | ||||
|             old_feats = [{{ module }}.layers.vector.features[0]]; | ||||
|             {{ module }}.layers.vector.removeFeatures(old_feats); | ||||
|             {{ module }}.layers.vector.destroyFeatures(old_feats); | ||||
|         } | ||||
|         {{ module }}.write_wkt(event.feature); | ||||
|     } | ||||
| }; | ||||
| {{ module }}.modify_wkt = function(event){ | ||||
|     if ({{ module }}.is_collection){ | ||||
|         if ({{ module }}.is_point){ | ||||
|             {{ module }}.add_wkt(event); | ||||
|             return; | ||||
|         } else { | ||||
|             // When modifying the selected components are added to the | ||||
|             // vector layer so we only increment to the `num_geom` value. | ||||
|             var feat = new OpenLayers.Feature.Vector(new OpenLayers.Geometry.{{ geom_type }}()); | ||||
|             for (var i = 0; i < {{ module }}.num_geom; i++){ | ||||
|                 feat.geometry.addComponents([{{ module }}.layers.vector.features[i].geometry]); | ||||
|             } | ||||
|             {{ module }}.write_wkt(feat); | ||||
|         } | ||||
|     } else { | ||||
|         {{ module }}.write_wkt(event.feature); | ||||
|     } | ||||
| }; | ||||
| // Function to clear vector features and purge wkt from div | ||||
| {{ module }}.deleteFeatures = function(){ | ||||
|     {{ module }}.layers.vector.removeFeatures({{ module }}.layers.vector.features); | ||||
|     {{ module }}.layers.vector.destroyFeatures(); | ||||
| }; | ||||
| {{ module }}.clearFeatures = function (){ | ||||
|     {{ module }}.deleteFeatures(); | ||||
|     document.getElementById('{{ id }}').value = ''; | ||||
|     {% localize off %} | ||||
|     {{ module }}.map.setCenter(new OpenLayers.LonLat({{ default_lon }}, {{ default_lat }}), {{ default_zoom }}); | ||||
|     {% endlocalize %} | ||||
| }; | ||||
| // Add Select control | ||||
| {{ module }}.addSelectControl = function(){ | ||||
|     var select = new OpenLayers.Control.SelectFeature({{ module }}.layers.vector, {'toggle' : true, 'clickout' : true}); | ||||
|     {{ module }}.map.addControl(select); | ||||
|     select.activate(); | ||||
| }; | ||||
| {{ module }}.enableDrawing = function(){ | ||||
|     {{ module }}.map.getControlsByClass('OpenLayers.Control.DrawFeature')[0].activate(); | ||||
| }; | ||||
| {{ module }}.enableEditing = function(){ | ||||
|     {{ module }}.map.getControlsByClass('OpenLayers.Control.ModifyFeature')[0].activate(); | ||||
| }; | ||||
| // Create an array of controls based on geometry type | ||||
| {{ module }}.getControls = function(lyr){ | ||||
|     {{ module }}.panel = new OpenLayers.Control.Panel({'displayClass': 'olControlEditingToolbar'}); | ||||
|     {{ module }}.controls = [new OpenLayers.Control.Navigation()]; | ||||
|     if (!{{ module }}.modifiable && lyr.features.length) return; | ||||
|     if ({{ module }}.is_linestring || {{ module }}.is_generic){ | ||||
|         {{ module }}.controls.push(new OpenLayers.Control.DrawFeature(lyr, OpenLayers.Handler.Path, {'displayClass': 'olControlDrawFeaturePath'})); | ||||
|     } | ||||
|     if ({{ module }}.is_polygon || {{ module }}.is_generic){ | ||||
|         {{ module }}.controls.push(new OpenLayers.Control.DrawFeature(lyr, OpenLayers.Handler.Polygon, {'displayClass': 'olControlDrawFeaturePolygon'})); | ||||
|     } | ||||
|     if ({{ module }}.is_point || {{ module }}.is_generic){ | ||||
|         {{ module }}.controls.push(new OpenLayers.Control.DrawFeature(lyr, OpenLayers.Handler.Point, {'displayClass': 'olControlDrawFeaturePoint'})); | ||||
|     } | ||||
|     if ({{ module }}.modifiable){ | ||||
|         {{ module }}.controls.push(new OpenLayers.Control.ModifyFeature(lyr, {'displayClass': 'olControlModifyFeature'})); | ||||
|     } | ||||
| }; | ||||
| {{ module }}.init = function(){ | ||||
|     {% block map_options %}// The options hash, w/ zoom, resolution, and projection settings. | ||||
|     var options = { | ||||
| {% autoescape off %}{% for item in map_options.items %}      '{{ item.0 }}' : {{ item.1 }}{% if not forloop.last %},{% endif %} | ||||
| {% endfor %}{% endautoescape %}    };{% endblock %} | ||||
|     // The admin map for this geometry field. | ||||
|     {% block map_creation %} | ||||
|     {{ module }}.map = new OpenLayers.Map('{{ id }}_map', options); | ||||
|     // Base Layer | ||||
|     {{ module }}.layers.base = {% block base_layer %}new OpenLayers.Layer.WMS("{{ wms_name }}", "{{ wms_url }}", {layers: '{{ wms_layer }}'{{ wms_options|safe }}});{% endblock %} | ||||
|     {{ module }}.map.addLayer({{ module }}.layers.base); | ||||
|     {% endblock %} | ||||
|     {% block extra_layers %}{% endblock %} | ||||
|     {% if is_linestring %}OpenLayers.Feature.Vector.style["default"]["strokeWidth"] = 3; // Default too thin for linestrings. {% endif %} | ||||
|     {{ module }}.layers.vector = new OpenLayers.Layer.Vector(" {{ field_name }}"); | ||||
|     {{ module }}.map.addLayer({{ module }}.layers.vector); | ||||
|     // Read WKT from the text field. | ||||
|     var wkt = document.getElementById('{{ id }}').value; | ||||
|     if (wkt){ | ||||
|         // After reading into geometry, immediately write back to | ||||
|         // WKT <textarea> as EWKT (so that SRID is included). | ||||
|         var admin_geom = {{ module }}.read_wkt(wkt); | ||||
|         {{ module }}.write_wkt(admin_geom); | ||||
|         if ({{ module }}.is_collection){ | ||||
|             // If geometry collection, add each component individually so they may be | ||||
|             // edited individually. | ||||
|             for (var i = 0; i < {{ module }}.num_geom; i++){ | ||||
|                 {{ module }}.layers.vector.addFeatures([new OpenLayers.Feature.Vector(admin_geom.geometry.components[i].clone())]); | ||||
|             } | ||||
|         } else { | ||||
|             {{ module }}.layers.vector.addFeatures([admin_geom]); | ||||
|         } | ||||
|         // Zooming to the bounds. | ||||
|         {{ module }}.map.zoomToExtent(admin_geom.geometry.getBounds()); | ||||
|         if ({{ module }}.is_point){ | ||||
|             {{ module }}.map.zoomTo({{ point_zoom }}); | ||||
|         } | ||||
|     } else { | ||||
|         {% localize off %} | ||||
|         {{ module }}.map.setCenter(new OpenLayers.LonLat({{ default_lon }}, {{ default_lat }}), {{ default_zoom }}); | ||||
|         {% endlocalize %} | ||||
|     } | ||||
|     // This allows editing of the geographic fields -- the modified WKT is | ||||
|     // written back to the content field (as EWKT, so that the ORM will know | ||||
|     // to transform back to original SRID). | ||||
|     {{ module }}.layers.vector.events.on({"featuremodified" : {{ module }}.modify_wkt}); | ||||
|     {{ module }}.layers.vector.events.on({"featureadded" : {{ module }}.add_wkt}); | ||||
|     {% block controls %} | ||||
|     // Map controls: | ||||
|     // Add geometry specific panel of toolbar controls | ||||
|     {{ module }}.getControls({{ module }}.layers.vector); | ||||
|     {{ module }}.panel.addControls({{ module }}.controls); | ||||
|     {{ module }}.map.addControl({{ module }}.panel); | ||||
|     {{ module }}.addSelectControl(); | ||||
|     // Then add optional visual controls | ||||
|     {% if mouse_position %}{{ module }}.map.addControl(new OpenLayers.Control.MousePosition());{% endif %} | ||||
|     {% if scale_text %}{{ module }}.map.addControl(new OpenLayers.Control.Scale());{% endif %} | ||||
|     {% if layerswitcher %}{{ module }}.map.addControl(new OpenLayers.Control.LayerSwitcher());{% endif %} | ||||
|     // Then add optional behavior controls | ||||
|     {% if not scrollable %}{{ module }}.map.getControlsByClass('OpenLayers.Control.Navigation')[0].disableZoomWheel();{% endif %} | ||||
|     {% endblock %} | ||||
|     if (wkt){ | ||||
|         if ({{ module }}.modifiable){ | ||||
|             {{ module }}.enableEditing(); | ||||
|         } | ||||
|     } else { | ||||
|         {{ module }}.enableDrawing(); | ||||
|     } | ||||
| }; | ||||
| @@ -1,2 +0,0 @@ | ||||
| {% extends "gis/admin/openlayers.html" %} | ||||
| {% block openlayers %}{% include "gis/admin/osm.js" %}{% endblock %} | ||||
| @@ -1,2 +0,0 @@ | ||||
| {% extends "gis/admin/openlayers.js" %} | ||||
| {% block base_layer %}new OpenLayers.Layer.OSM("OpenStreetMap (Mapnik)");{% endblock %} | ||||
| @@ -20,72 +20,3 @@ GeoDjango's admin site | ||||
|  | ||||
|         The keyword arguments that would be passed to the :attr:`gis_widget`. | ||||
|         Defaults to an empty dictionary. | ||||
|  | ||||
| ``GeoModelAdmin`` | ||||
| ================= | ||||
|  | ||||
| .. class:: GeoModelAdmin | ||||
|  | ||||
|     .. attribute:: default_lon | ||||
|  | ||||
|     The default center longitude. | ||||
|  | ||||
|     .. attribute:: default_lat | ||||
|  | ||||
|     The default center latitude. | ||||
|  | ||||
|     .. attribute:: default_zoom | ||||
|  | ||||
|     The default zoom level to use.  Defaults to 4. | ||||
|  | ||||
|     .. attribute:: extra_js | ||||
|  | ||||
|     Sequence of URLs to any extra JavaScript to include. | ||||
|  | ||||
|     .. attribute:: map_template | ||||
|  | ||||
|     Override the template used to generate the JavaScript slippy map. | ||||
|     Default is ``'gis/admin/openlayers.html'``. | ||||
|  | ||||
|     .. attribute:: map_width | ||||
|  | ||||
|     Width of the map, in pixels.  Defaults to 600. | ||||
|  | ||||
|     .. attribute:: map_height | ||||
|  | ||||
|     Height of the map, in pixels.  Defaults to 400. | ||||
|  | ||||
|     .. attribute:: openlayers_url | ||||
|  | ||||
|     Link to the URL of the OpenLayers JavaScript.  Defaults to | ||||
|     ``'https://cdnjs.cloudflare.com/ajax/libs/openlayers/2.13.1/OpenLayers.js'``. | ||||
|  | ||||
|     .. attribute:: modifiable | ||||
|  | ||||
|     Defaults to ``True``.  When set to ``False``, disables editing of | ||||
|     existing geometry fields in the admin. | ||||
|  | ||||
|     .. note:: | ||||
|  | ||||
|         This is different from adding the geometry field to | ||||
|         :attr:`~django.contrib.admin.ModelAdmin.readonly_fields`, | ||||
|         which will only display the WKT of the geometry. Setting | ||||
|         ``modifiable=False``, actually displays the geometry in a map, | ||||
|         but disables the ability to edit its vertices. | ||||
|  | ||||
|     .. deprecated:: 4.0 | ||||
|  | ||||
|         This class is deprecated. Use :class:`~django.contrib.admin.ModelAdmin` | ||||
|         instead. | ||||
|  | ||||
| ``OSMGeoAdmin`` | ||||
| =============== | ||||
|  | ||||
| .. class:: OSMGeoAdmin | ||||
|  | ||||
|     A subclass of :class:`GeoModelAdmin` that uses a Spherical Mercator projection | ||||
|     with `OpenStreetMap <https://www.openstreetmap.org/>`_ street data tiles. | ||||
|  | ||||
|     .. deprecated:: 4.0 | ||||
|  | ||||
|         This class is deprecated. Use :class:`GISModelAdmin` instead. | ||||
|   | ||||
| @@ -294,6 +294,9 @@ to remove usage of these features. | ||||
|   * ``django.db.models.functions.TruncQuarter()`` | ||||
|   * ``django.db.models.functions.TruncYear()`` | ||||
|  | ||||
| * The ``django.contrib.gis.admin.GeoModelAdmin`` and ``OSMGeoAdmin`` classes | ||||
|   are removed. | ||||
|  | ||||
| See :ref:`deprecated-features-4.1` for details on these changes, including how | ||||
| to remove usage of these features. | ||||
|  | ||||
|   | ||||
| @@ -4,5 +4,3 @@ except ImportError: | ||||
|     from django.contrib import admin | ||||
|  | ||||
|     admin.GISModelAdmin = admin.ModelAdmin | ||||
|     # RemovedInDjango50Warning. | ||||
|     admin.OSMGeoAdmin = admin.ModelAdmin | ||||
|   | ||||
| @@ -1,5 +0,0 @@ | ||||
| from django.contrib.gis import admin | ||||
|  | ||||
|  | ||||
| class UnmodifiableAdmin(admin.OSMGeoAdmin): | ||||
|     modifiable = False | ||||
| @@ -1,21 +0,0 @@ | ||||
| from django.contrib.gis.db import models | ||||
| from django.test import ignore_warnings | ||||
| from django.utils.deprecation import RemovedInDjango50Warning | ||||
|  | ||||
| from ..admin import admin | ||||
|  | ||||
|  | ||||
| class City(models.Model): | ||||
|     name = models.CharField(max_length=30) | ||||
|     point = models.PointField() | ||||
|  | ||||
|     class Meta: | ||||
|         app_label = "geoadmini_deprecated" | ||||
|  | ||||
|     def __str__(self): | ||||
|         return self.name | ||||
|  | ||||
|  | ||||
| site = admin.AdminSite(name="admin_gis") | ||||
| with ignore_warnings(category=RemovedInDjango50Warning): | ||||
|     site.register(City, admin.OSMGeoAdmin) | ||||
| @@ -1,132 +0,0 @@ | ||||
| from django.contrib.gis import admin | ||||
| from django.contrib.gis.geos import Point | ||||
| from django.test import SimpleTestCase, ignore_warnings, override_settings | ||||
| from django.utils.deprecation import RemovedInDjango50Warning | ||||
|  | ||||
| from .admin import UnmodifiableAdmin | ||||
| from .models import City, site | ||||
|  | ||||
|  | ||||
| @ignore_warnings(category=RemovedInDjango50Warning) | ||||
| @override_settings(ROOT_URLCONF="django.contrib.gis.tests.geoadmin.urls") | ||||
| class GeoAdminTest(SimpleTestCase): | ||||
|     def test_ensure_geographic_media(self): | ||||
|         geoadmin = site._registry[City] | ||||
|         admin_js = geoadmin.media.render_js() | ||||
|         self.assertTrue(any(geoadmin.openlayers_url in js for js in admin_js)) | ||||
|  | ||||
|     def test_olmap_OSM_rendering(self): | ||||
|         delete_all_btn = ( | ||||
|             '<a href="javascript:geodjango_point.clearFeatures()">Delete all Features' | ||||
|             "</a>" | ||||
|         ) | ||||
|         original_geoadmin = site._registry[City] | ||||
|         params = original_geoadmin.get_map_widget(City._meta.get_field("point")).params | ||||
|         result = original_geoadmin.get_map_widget( | ||||
|             City._meta.get_field("point") | ||||
|         )().render("point", Point(-79.460734, 40.18476), params) | ||||
|         self.assertIn( | ||||
|             "geodjango_point.layers.base = " | ||||
|             'new OpenLayers.Layer.OSM("OpenStreetMap (Mapnik)");', | ||||
|             result, | ||||
|         ) | ||||
|  | ||||
|         self.assertIn(delete_all_btn, result) | ||||
|  | ||||
|         site.unregister(City) | ||||
|         site.register(City, UnmodifiableAdmin) | ||||
|         try: | ||||
|             geoadmin = site._registry[City] | ||||
|             params = geoadmin.get_map_widget(City._meta.get_field("point")).params | ||||
|             result = geoadmin.get_map_widget(City._meta.get_field("point"))().render( | ||||
|                 "point", Point(-79.460734, 40.18476), params | ||||
|             ) | ||||
|  | ||||
|             self.assertNotIn(delete_all_btn, result) | ||||
|         finally: | ||||
|             site.unregister(City) | ||||
|             site.register(City, original_geoadmin.__class__) | ||||
|  | ||||
|     def test_olmap_WMS_rendering(self): | ||||
|         geoadmin = admin.GeoModelAdmin(City, site) | ||||
|         result = geoadmin.get_map_widget(City._meta.get_field("point"))().render( | ||||
|             "point", Point(-79.460734, 40.18476) | ||||
|         ) | ||||
|         self.assertIn( | ||||
|             'geodjango_point.layers.base = new OpenLayers.Layer.WMS("OpenLayers WMS", ' | ||||
|             '"http://vmap0.tiles.osgeo.org/wms/vmap0", ' | ||||
|             "{layers: 'basic', format: 'image/jpeg'});", | ||||
|             result, | ||||
|         ) | ||||
|  | ||||
|     def test_olwidget_has_changed(self): | ||||
|         """ | ||||
|         Changes are accurately noticed by OpenLayersWidget. | ||||
|         """ | ||||
|         geoadmin = site._registry[City] | ||||
|         form = geoadmin.get_changelist_form(None)() | ||||
|         has_changed = form.fields["point"].has_changed | ||||
|  | ||||
|         initial = Point(13.4197458572965953, 52.5194108501149799, srid=4326) | ||||
|         data_same = "SRID=3857;POINT(1493879.2754093995 6894592.019687599)" | ||||
|         data_almost_same = "SRID=3857;POINT(1493879.2754093990 6894592.019687590)" | ||||
|         data_changed = "SRID=3857;POINT(1493884.0527237 6894593.8111804)" | ||||
|  | ||||
|         self.assertTrue(has_changed(None, data_changed)) | ||||
|         self.assertTrue(has_changed(initial, "")) | ||||
|         self.assertFalse(has_changed(None, "")) | ||||
|         self.assertFalse(has_changed(initial, data_same)) | ||||
|         self.assertFalse(has_changed(initial, data_almost_same)) | ||||
|         self.assertTrue(has_changed(initial, data_changed)) | ||||
|  | ||||
|     def test_olwidget_empty_string(self): | ||||
|         geoadmin = site._registry[City] | ||||
|         form = geoadmin.get_changelist_form(None)({"point": ""}) | ||||
|         with self.assertNoLogs("django.contrib.gis", "ERROR"): | ||||
|             output = str(form["point"]) | ||||
|         self.assertInHTML( | ||||
|             '<textarea id="id_point" class="vWKTField required" cols="150"' | ||||
|             ' rows="10" name="point"></textarea>', | ||||
|             output, | ||||
|         ) | ||||
|  | ||||
|     def test_olwidget_invalid_string(self): | ||||
|         geoadmin = site._registry[City] | ||||
|         form = geoadmin.get_changelist_form(None)({"point": "INVALID()"}) | ||||
|         with self.assertLogs("django.contrib.gis", "ERROR") as cm: | ||||
|             output = str(form["point"]) | ||||
|         self.assertInHTML( | ||||
|             '<textarea id="id_point" class="vWKTField required" cols="150"' | ||||
|             ' rows="10" name="point"></textarea>', | ||||
|             output, | ||||
|         ) | ||||
|         self.assertEqual(len(cm.records), 1) | ||||
|         self.assertEqual( | ||||
|             cm.records[0].getMessage(), | ||||
|             "Error creating geometry from value 'INVALID()' (String input " | ||||
|             "unrecognized as WKT EWKT, and HEXEWKB.)", | ||||
|         ) | ||||
|  | ||||
|  | ||||
| class DeprecationTests(SimpleTestCase): | ||||
|     def test_warning(self): | ||||
|         class DeprecatedOSMGeoAdmin(admin.OSMGeoAdmin): | ||||
|             pass | ||||
|  | ||||
|         class DeprecatedGeoModelAdmin(admin.GeoModelAdmin): | ||||
|             pass | ||||
|  | ||||
|         msg = ( | ||||
|             "django.contrib.gis.admin.GeoModelAdmin and OSMGeoAdmin are " | ||||
|             "deprecated in favor of django.contrib.admin.ModelAdmin and " | ||||
|             "django.contrib.gis.admin.GISModelAdmin." | ||||
|         ) | ||||
|         with self.assertRaisesMessage(RemovedInDjango50Warning, msg): | ||||
|             DeprecatedOSMGeoAdmin(City, site) | ||||
|         with self.assertRaisesMessage(RemovedInDjango50Warning, msg): | ||||
|             DeprecatedGeoModelAdmin(City, site) | ||||
|  | ||||
|     def test_openlayerswidget_warning(self): | ||||
|         msg = "django.contrib.gis.admin.OpenLayersWidget is deprecated." | ||||
|         with self.assertRaisesMessage(RemovedInDjango50Warning, msg): | ||||
|             admin.OpenLayersWidget() | ||||
| @@ -1,6 +0,0 @@ | ||||
| from django.contrib import admin | ||||
| from django.urls import include, path | ||||
|  | ||||
| urlpatterns = [ | ||||
|     path("admin/", include(admin.site.urls)), | ||||
| ] | ||||
		Reference in New Issue
	
	Block a user