Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fixed #5472 --Added OpenLayers-based widgets in contrib.gis
Largely inspired from django-floppyforms. Designed to not depend on OpenLayers at code level.
- Loading branch information
Showing
12 changed files
with
931 additions
and
20 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -1,2 +1,5 @@ | |||
from django.forms import * | from django.forms import * | ||
from django.contrib.gis.forms.fields import GeometryField | from .fields import (GeometryField, GeometryCollectionField, PointField, | ||
MultiPointField, LineStringField, MultiLineStringField, PolygonField, | |||
MultiPolygonField) | |||
from .widgets import BaseGeometryWidget, OpenLayersWidget, OSMWidget |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -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}) |
Oops, something went wrong.