diff options
| author | Claude Paroz <claude@2xlibre.net> | 2013-03-16 11:39:18 +0100 |
|---|---|---|
| committer | Claude Paroz <claude@2xlibre.net> | 2013-05-17 13:33:40 +0200 |
| commit | b16b72d415808073da0418de93bf32f71ead959d (patch) | |
| tree | 7006c92c5672fbfd5ca09f9e3f175550ca951adb /django/contrib/gis/forms/widgets.py | |
| parent | d4d114563280b6e202b8459be0aa471621c7b563 (diff) | |
Fixed #5472 --Added OpenLayers-based widgets in contrib.gis
Largely inspired from django-floppyforms. Designed to not depend
on OpenLayers at code level.
Diffstat (limited to 'django/contrib/gis/forms/widgets.py')
| -rw-r--r-- | django/contrib/gis/forms/widgets.py | 112 |
1 files changed, 112 insertions, 0 deletions
diff --git a/django/contrib/gis/forms/widgets.py b/django/contrib/gis/forms/widgets.py new file mode 100644 index 0000000000..d50c7c005a --- /dev/null +++ b/django/contrib/gis/forms/widgets.py @@ -0,0 +1,112 @@ +from __future__ import unicode_literals + +import logging + +from django.conf import settings +from django.contrib.gis import gdal +from django.contrib.gis.geos import GEOSGeometry, GEOSException +from django.forms.widgets import Widget +from django.template import loader +from django.utils import six +from django.utils import translation + +logger = logging.getLogger('django.contrib.gis') + + +class BaseGeometryWidget(Widget): + """ + The base class for rich geometry widgets. + Renders a map using the WKT of the geometry. + """ + geom_type = 'GEOMETRY' + map_srid = 4326 + map_width = 600 + map_height = 400 + display_wkt = False + + supports_3d = False + template_name = '' # set on subclasses + + def __init__(self, attrs=None): + self.attrs = {} + for key in ('geom_type', 'map_srid', 'map_width', 'map_height', 'display_wkt'): + self.attrs[key] = getattr(self, key) + if attrs: + self.attrs.update(attrs) + + def render(self, name, value, attrs=None): + # If a string reaches here (via a validation error on another + # field) then just reconstruct the Geometry. + if isinstance(value, six.string_types): + try: + value = GEOSGeometry(value) + except (GEOSException, ValueError) as err: + logger.error( + "Error creating geometry from value '%s' (%s)" % ( + value, err) + ) + value = None + + wkt = '' + if value: + # Check that srid of value and map match + if value.srid != self.map_srid: + try: + ogr = value.ogr + ogr.transform(self.map_srid) + wkt = ogr.wkt + except gdal.OGRException as err: + logger.error( + "Error transforming geometry from srid '%s' to srid '%s' (%s)" % ( + value.srid, self.map_srid, err) + ) + else: + wkt = value.wkt + + context = self.build_attrs(attrs, + name=name, + module='geodjango_%s' % name.replace('-','_'), # JS-safe + wkt=wkt, + geom_type=gdal.OGRGeomType(self.attrs['geom_type']), + STATIC_URL=settings.STATIC_URL, + LANGUAGE_BIDI=translation.get_language_bidi(), + ) + return loader.render_to_string(self.template_name, context) + + +class OpenLayersWidget(BaseGeometryWidget): + template_name = 'gis/openlayers.html' + class Media: + js = ( + 'http://openlayers.org/api/2.11/OpenLayers.js', + 'gis/js/OLMapWidget.js', + ) + + +class OSMWidget(BaseGeometryWidget): + """ + An OpenLayers/OpenStreetMap-based widget. + """ + template_name = 'gis/openlayers-osm.html' + default_lon = 5 + default_lat = 47 + + class Media: + js = ( + 'http://openlayers.org/api/2.11/OpenLayers.js', + 'http://www.openstreetmap.org/openlayers/OpenStreetMap.js', + 'gis/js/OLMapWidget.js', + ) + + @property + def map_srid(self): + # Use the official spherical mercator projection SRID on versions + # of GDAL that support it; otherwise, fallback to 900913. + if gdal.HAS_GDAL and gdal.GDAL_VERSION >= (1, 7): + return 3857 + else: + return 900913 + + def render(self, name, value, attrs=None): + return super(self, OSMWidget).render(name, value, + {'default_lon': self.default_lon, 'default_lat': self.default_lat}) |
