mirror of
https://github.com/django/django.git
synced 2025-03-29 02:30:48 +00:00
Refs #27674 -- Removed GeoModelAdmin and OSMGeoAdmin per deprecation timeline.
This commit is contained in:
parent
2fad163257
commit
4982958ec0
@ -11,7 +11,7 @@ from django.contrib.admin import (
|
|||||||
register,
|
register,
|
||||||
site,
|
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
|
from django.contrib.gis.admin.widgets import OpenLayersWidget
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
@ -28,7 +28,5 @@ __all__ = [
|
|||||||
"site",
|
"site",
|
||||||
"GISModelAdmin",
|
"GISModelAdmin",
|
||||||
# RemovedInDjango50Warning.
|
# RemovedInDjango50Warning.
|
||||||
"GeoModelAdmin",
|
|
||||||
"OpenLayersWidget",
|
"OpenLayersWidget",
|
||||||
"OSMGeoAdmin",
|
|
||||||
]
|
]
|
||||||
|
@ -1,12 +1,6 @@
|
|||||||
import warnings
|
|
||||||
|
|
||||||
from django.contrib.admin import ModelAdmin
|
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.db import models
|
||||||
from django.contrib.gis.forms import OSMWidget
|
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:
|
class GeoModelAdminMixin:
|
||||||
@ -25,156 +19,3 @@ class GeoModelAdminMixin:
|
|||||||
|
|
||||||
class GISModelAdmin(GeoModelAdminMixin, ModelAdmin):
|
class GISModelAdmin(GeoModelAdminMixin, ModelAdmin):
|
||||||
pass
|
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`.
|
The keyword arguments that would be passed to the :attr:`gis_widget`.
|
||||||
Defaults to an empty dictionary.
|
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.TruncQuarter()``
|
||||||
* ``django.db.models.functions.TruncYear()``
|
* ``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
|
See :ref:`deprecated-features-4.1` for details on these changes, including how
|
||||||
to remove usage of these features.
|
to remove usage of these features.
|
||||||
|
|
||||||
|
@ -4,5 +4,3 @@ except ImportError:
|
|||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
|
|
||||||
admin.GISModelAdmin = admin.ModelAdmin
|
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)),
|
|
||||||
]
|
|
Loading…
x
Reference in New Issue
Block a user