app/django/contrib/gis/admin/widgets.py
changeset 323 ff1a9aa48cfd
equal deleted inserted replaced
322:6641e941ef1e 323:ff1a9aa48cfd
       
     1 from django.contrib.gis.gdal import OGRException
       
     2 from django.contrib.gis.geos import GEOSGeometry, GEOSException
       
     3 from django.forms.widgets import Textarea
       
     4 from django.template.loader import render_to_string
       
     5 
       
     6 class OpenLayersWidget(Textarea):
       
     7     """
       
     8     Renders an OpenLayers map using the WKT of the geometry.
       
     9     """
       
    10     def render(self, name, value, attrs=None):
       
    11         # Update the template parameters with any attributes passed in.
       
    12         if attrs: self.params.update(attrs)
       
    13 
       
    14         # Defaulting the WKT value to a blank string -- this
       
    15         # will be tested in the JavaScript and the appropriate
       
    16         # interfaace will be constructed.
       
    17         self.params['wkt'] = ''
       
    18 
       
    19         # If a string reaches here (via a validation error on another
       
    20         # field) then just reconstruct the Geometry.
       
    21         if isinstance(value, basestring):
       
    22             try:
       
    23                 value = GEOSGeometry(value)
       
    24             except (GEOSException, ValueError):
       
    25                 value = None
       
    26 
       
    27         if value and value.geom_type.upper() != self.geom_type:
       
    28             value = None
       
    29 
       
    30         # Constructing the dictionary of the map options.
       
    31         self.params['map_options'] = self.map_options()
       
    32 
       
    33         # Constructing the JavaScript module name using the ID of
       
    34         # the GeometryField (passed in via the `attrs` keyword).
       
    35         self.params['module'] = 'geodjango_%s' % self.params['field_name']
       
    36 
       
    37         if value:
       
    38             # Transforming the geometry to the projection used on the
       
    39             # OpenLayers map.
       
    40             srid = self.params['srid']
       
    41             if value.srid != srid: 
       
    42                 try:
       
    43                     value.transform(srid)
       
    44                     wkt = value.wkt
       
    45                 except OGRException:
       
    46                     wkt = ''
       
    47             else:
       
    48                 wkt = value.wkt
       
    49                
       
    50             # Setting the parameter WKT with that of the transformed
       
    51             # geometry.
       
    52             self.params['wkt'] = wkt
       
    53 
       
    54         return render_to_string(self.template, self.params)
       
    55     
       
    56     def map_options(self):
       
    57         "Builds the map options hash for the OpenLayers template."
       
    58 
       
    59         # JavaScript construction utilities for the Bounds and Projection.
       
    60         def ol_bounds(extent):
       
    61             return 'new OpenLayers.Bounds(%s)' % str(extent)
       
    62         def ol_projection(srid):
       
    63             return 'new OpenLayers.Projection("EPSG:%s")' % srid
       
    64 
       
    65         # An array of the parameter name, the name of their OpenLayers
       
    66         # counterpart, and the type of variable they are.
       
    67         map_types = [('srid', 'projection', 'srid'), 
       
    68                      ('display_srid', 'displayProjection', 'srid'), 
       
    69                      ('units', 'units', str),
       
    70                      ('max_resolution', 'maxResolution', float),
       
    71                      ('max_extent', 'maxExtent', 'bounds'),
       
    72                      ('num_zoom', 'numZoomLevels', int),
       
    73                      ('max_zoom', 'maxZoomLevels', int),
       
    74                      ('min_zoom', 'minZoomLevel', int),
       
    75                      ]
       
    76 
       
    77         # Building the map options hash.
       
    78         map_options = {}
       
    79         for param_name, js_name, option_type in map_types:
       
    80             if self.params.get(param_name, False):
       
    81                 if option_type == 'srid':
       
    82                     value = ol_projection(self.params[param_name])
       
    83                 elif option_type == 'bounds':
       
    84                     value = ol_bounds(self.params[param_name])
       
    85                 elif option_type in (float, int):
       
    86                     value = self.params[param_name]
       
    87                 elif option_type in (str,):
       
    88                     value = '"%s"' % self.params[param_name]
       
    89                 else:
       
    90                     raise TypeError
       
    91                 map_options[js_name] = value
       
    92         return map_options