123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869 |
- """
- The GeometryProxy object, allows for lazy-geometries. The proxy uses
- Python descriptors for instantiating and setting Geometry objects
- corresponding to geographic model fields.
- Thanks to Robert Coup for providing this functionality (see #4322).
- """
- from django.contrib.gis import memoryview
- from django.utils import six
- class GeometryProxy(object):
- def __init__(self, klass, field):
- """
- Proxy initializes on the given Geometry class (not an instance) and
- the GeometryField.
- """
- self._field = field
- self._klass = klass
- def __get__(self, obj, type=None):
- """
- This accessor retrieves the geometry, initializing it using the geometry
- class specified during initialization and the HEXEWKB value of the field.
- Currently, only GEOS or OGR geometries are supported.
- """
- if obj is None:
- # Accessed on a class, not an instance
- return self
- # Getting the value of the field.
- geom_value = obj.__dict__[self._field.attname]
- if isinstance(geom_value, self._klass):
- geom = geom_value
- elif (geom_value is None) or (geom_value == ''):
- geom = None
- else:
- # Otherwise, a Geometry object is built using the field's contents,
- # and the model's corresponding attribute is set.
- geom = self._klass(geom_value)
- setattr(obj, self._field.attname, geom)
- return geom
- def __set__(self, obj, value):
- """
- This accessor sets the proxied geometry with the geometry class
- specified during initialization. Values of None, HEXEWKB, or WKT may
- be used to set the geometry as well.
- """
- # The OGC Geometry type of the field.
- gtype = self._field.geom_type
- # The geometry type must match that of the field -- unless the
- # general GeometryField is used.
- if isinstance(value, self._klass) and (str(value.geom_type).upper() == gtype or gtype == 'GEOMETRY'):
- # Assigning the SRID to the geometry.
- if value.srid is None:
- value.srid = self._field.srid
- elif value is None or isinstance(value, six.string_types + (memoryview,)):
- # Set with None, WKT, HEX, or WKB
- pass
- else:
- raise TypeError('Cannot set %s GeometryProxy (%s) with value of type: %s' % (
- obj.__class__.__name__, gtype, type(value)))
- # Setting the objects dictionary with the value, and returning.
- obj.__dict__[self._field.attname] = value
- return value
|