app/django/contrib/gis/admin/widgets.py
author Madhusudan C.S. <madhusudancs@gmail.com>
Mon, 08 Jun 2009 08:42:13 +0200
changeset 2406 6f966e1a80bc
parent 323 ff1a9aa48cfd
permissions -rw-r--r--
Changed the property that holds the minimum age required for Students to participate in a GHOP based program. Added a new property student_min_age_as_of to hold the DateTime from when the minimum age should be reached. Changed student_min_age property to now store the student minimum age as an integer. This all feel more user friendly then letting the program admin calculate the required DateTime. Storing the two properties is then still needed in this case since information might be lost otherwise when the program admin brings up the edit view. Reviewed by: Lennard de Rijk

from django.contrib.gis.gdal import OGRException
from django.contrib.gis.geos import GEOSGeometry, GEOSException
from django.forms.widgets import Textarea
from django.template.loader import render_to_string

class OpenLayersWidget(Textarea):
    """
    Renders an OpenLayers map using the WKT of the geometry.
    """
    def render(self, name, value, attrs=None):
        # Update the template parameters with any attributes passed in.
        if attrs: self.params.update(attrs)

        # Defaulting the WKT value to a blank string -- this
        # will be tested in the JavaScript and the appropriate
        # interfaace will be constructed.
        self.params['wkt'] = ''

        # If a string reaches here (via a validation error on another
        # field) then just reconstruct the Geometry.
        if isinstance(value, basestring):
            try:
                value = GEOSGeometry(value)
            except (GEOSException, ValueError):
                value = None

        if value and value.geom_type.upper() != self.geom_type:
            value = None

        # Constructing the dictionary of the map options.
        self.params['map_options'] = self.map_options()

        # Constructing the JavaScript module name using the ID of
        # the GeometryField (passed in via the `attrs` keyword).
        self.params['module'] = 'geodjango_%s' % self.params['field_name']

        if value:
            # Transforming the geometry to the projection used on the
            # OpenLayers map.
            srid = self.params['srid']
            if value.srid != srid: 
                try:
                    value.transform(srid)
                    wkt = value.wkt
                except OGRException:
                    wkt = ''
            else:
                wkt = value.wkt
               
            # Setting the parameter WKT with that of the transformed
            # geometry.
            self.params['wkt'] = wkt

        return render_to_string(self.template, self.params)
    
    def map_options(self):
        "Builds the map options hash for the OpenLayers template."

        # JavaScript construction utilities for the Bounds and Projection.
        def ol_bounds(extent):
            return 'new OpenLayers.Bounds(%s)' % str(extent)
        def ol_projection(srid):
            return 'new OpenLayers.Projection("EPSG:%s")' % srid

        # An array of the parameter name, the name of their OpenLayers
        # counterpart, and the type of variable they are.
        map_types = [('srid', 'projection', 'srid'), 
                     ('display_srid', 'displayProjection', 'srid'), 
                     ('units', 'units', str),
                     ('max_resolution', 'maxResolution', float),
                     ('max_extent', 'maxExtent', 'bounds'),
                     ('num_zoom', 'numZoomLevels', int),
                     ('max_zoom', 'maxZoomLevels', int),
                     ('min_zoom', 'minZoomLevel', int),
                     ]

        # Building the map options hash.
        map_options = {}
        for param_name, js_name, option_type in map_types:
            if self.params.get(param_name, False):
                if option_type == 'srid':
                    value = ol_projection(self.params[param_name])
                elif option_type == 'bounds':
                    value = ol_bounds(self.params[param_name])
                elif option_type in (float, int):
                    value = self.params[param_name]
                elif option_type in (str,):
                    value = '"%s"' % self.params[param_name]
                else:
                    raise TypeError
                map_options[js_name] = value
        return map_options