web/lib/django/contrib/gis/admin/widgets.py
changeset 0 0d40e90630ef
equal deleted inserted replaced
-1:000000000000 0:0d40e90630ef
       
     1 from django.conf import settings
       
     2 from django.contrib.gis.gdal import OGRException
       
     3 from django.contrib.gis.geos import GEOSGeometry, GEOSException
       
     4 from django.forms.widgets import Textarea
       
     5 from django.template import loader, Context
       
     6 from django.utils import translation
       
     7 
       
     8 # Creating a template context that contains Django settings
       
     9 # values needed by admin map templates.
       
    10 geo_context = Context({'ADMIN_MEDIA_PREFIX' : settings.ADMIN_MEDIA_PREFIX,
       
    11                        'LANGUAGE_BIDI' : translation.get_language_bidi(),
       
    12                        })
       
    13 
       
    14 class OpenLayersWidget(Textarea):
       
    15     """
       
    16     Renders an OpenLayers map using the WKT of the geometry.
       
    17     """
       
    18     def render(self, name, value, attrs=None):
       
    19         # Update the template parameters with any attributes passed in.
       
    20         if attrs: self.params.update(attrs)
       
    21 
       
    22         # Defaulting the WKT value to a blank string -- this
       
    23         # will be tested in the JavaScript and the appropriate
       
    24         # interface will be constructed.
       
    25         self.params['wkt'] = ''
       
    26 
       
    27         # If a string reaches here (via a validation error on another
       
    28         # field) then just reconstruct the Geometry.
       
    29         if isinstance(value, basestring):
       
    30             try:
       
    31                 value = GEOSGeometry(value)
       
    32             except (GEOSException, ValueError):
       
    33                 value = None
       
    34 
       
    35         if value and value.geom_type.upper() != self.geom_type:
       
    36             value = None
       
    37 
       
    38         # Constructing the dictionary of the map options.
       
    39         self.params['map_options'] = self.map_options()
       
    40 
       
    41         # Constructing the JavaScript module name using the name of
       
    42         # the GeometryField (passed in via the `attrs` keyword).
       
    43         # Use the 'name' attr for the field name (rather than 'field')
       
    44         self.params['name'] = name
       
    45         # note: we must switch out dashes for underscores since js
       
    46         # functions are created using the module variable
       
    47         js_safe_name = self.params['name'].replace('-','_')
       
    48         self.params['module'] = 'geodjango_%s' % js_safe_name
       
    49 
       
    50         if value:
       
    51             # Transforming the geometry to the projection used on the
       
    52             # OpenLayers map.
       
    53             srid = self.params['srid']
       
    54             if value.srid != srid:
       
    55                 try:
       
    56                     ogr = value.ogr
       
    57                     ogr.transform(srid)
       
    58                     wkt = ogr.wkt
       
    59                 except OGRException:
       
    60                     wkt = ''
       
    61             else:
       
    62                 wkt = value.wkt
       
    63 
       
    64             # Setting the parameter WKT with that of the transformed
       
    65             # geometry.
       
    66             self.params['wkt'] = wkt
       
    67 
       
    68         return loader.render_to_string(self.template, self.params,
       
    69                                        context_instance=geo_context)
       
    70 
       
    71     def map_options(self):
       
    72         "Builds the map options hash for the OpenLayers template."
       
    73 
       
    74         # JavaScript construction utilities for the Bounds and Projection.
       
    75         def ol_bounds(extent):
       
    76             return 'new OpenLayers.Bounds(%s)' % str(extent)
       
    77         def ol_projection(srid):
       
    78             return 'new OpenLayers.Projection("EPSG:%s")' % srid
       
    79 
       
    80         # An array of the parameter name, the name of their OpenLayers
       
    81         # counterpart, and the type of variable they are.
       
    82         map_types = [('srid', 'projection', 'srid'),
       
    83                      ('display_srid', 'displayProjection', 'srid'),
       
    84                      ('units', 'units', str),
       
    85                      ('max_resolution', 'maxResolution', float),
       
    86                      ('max_extent', 'maxExtent', 'bounds'),
       
    87                      ('num_zoom', 'numZoomLevels', int),
       
    88                      ('max_zoom', 'maxZoomLevels', int),
       
    89                      ('min_zoom', 'minZoomLevel', int),
       
    90                      ]
       
    91 
       
    92         # Building the map options hash.
       
    93         map_options = {}
       
    94         for param_name, js_name, option_type in map_types:
       
    95             if self.params.get(param_name, False):
       
    96                 if option_type == 'srid':
       
    97                     value = ol_projection(self.params[param_name])
       
    98                 elif option_type == 'bounds':
       
    99                     value = ol_bounds(self.params[param_name])
       
   100                 elif option_type in (float, int):
       
   101                     value = self.params[param_name]
       
   102                 elif option_type in (str,):
       
   103                     value = '"%s"' % self.params[param_name]
       
   104                 else:
       
   105                     raise TypeError
       
   106                 map_options[js_name] = value
       
   107         return map_options