web/lib/django/contrib/gis/db/models/proxy.py
author ymh <ymh.work@gmail.com>
Wed, 02 Jun 2010 18:57:35 +0200
changeset 38 77b6da96e6f1
permissions -rw-r--r--
update django
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
38
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
     1
"""
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
     2
The GeometryProxy object, allows for lazy-geometries.  The proxy uses
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
     3
Python descriptors for instantiating and setting Geometry objects
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
     4
corresponding to geographic model fields.
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
     5
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
     6
Thanks to Robert Coup for providing this functionality (see #4322).
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
     7
"""
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
     8
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
     9
class GeometryProxy(object):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    10
    def __init__(self, klass, field):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    11
        """
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    12
        Proxy initializes on the given Geometry class (not an instance) and
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    13
        the GeometryField.
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    14
        """
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    15
        self._field = field
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    16
        self._klass = klass
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    17
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    18
    def __get__(self, obj, type=None):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    19
        """
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    20
        This accessor retrieves the geometry, initializing it using the geometry
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    21
        class specified during initialization and the HEXEWKB value of the field.
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    22
        Currently, only GEOS or OGR geometries are supported.
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    23
        """
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    24
        if obj is None:
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    25
            # Accessed on a class, not an instance
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    26
            return self
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    27
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    28
        # Getting the value of the field.
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    29
        geom_value = obj.__dict__[self._field.attname]
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    30
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    31
        if isinstance(geom_value, self._klass):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    32
            geom = geom_value
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    33
        elif (geom_value is None) or (geom_value==''):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    34
            geom = None
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    35
        else:
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    36
            # Otherwise, a Geometry object is built using the field's contents,
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    37
            # and the model's corresponding attribute is set.
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    38
            geom = self._klass(geom_value)
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    39
            setattr(obj, self._field.attname, geom)
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    40
        return geom
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    41
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    42
    def __set__(self, obj, value):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    43
        """
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    44
        This accessor sets the proxied geometry with the geometry class
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    45
        specified during initialization.  Values of None, HEXEWKB, or WKT may
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    46
        be used to set the geometry as well.
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    47
        """
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    48
        # The OGC Geometry type of the field.
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    49
        gtype = self._field.geom_type
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    50
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    51
        # The geometry type must match that of the field -- unless the
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    52
        # general GeometryField is used.
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    53
        if isinstance(value, self._klass) and (str(value.geom_type).upper() == gtype or gtype == 'GEOMETRY'):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    54
            # Assigning the SRID to the geometry.
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    55
            if value.srid is None: value.srid = self._field.srid
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    56
        elif value is None or isinstance(value, (basestring, buffer)):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    57
            # Set with None, WKT, HEX, or WKB
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    58
            pass
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    59
        else:
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    60
            raise TypeError('cannot set %s GeometryProxy with value of type: %s' % (obj.__class__.__name__, type(value)))
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    61
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    62
        # Setting the objects dictionary with the value, and returning.
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    63
        obj.__dict__[self._field.attname] = value
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    64
        return value