diff -r b758351d191f -r cc9b7e14412b web/lib/django/contrib/gis/db/models/fields/__init__.py --- a/web/lib/django/contrib/gis/db/models/fields/__init__.py Wed May 19 17:43:59 2010 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,278 +0,0 @@ -from django.contrib.gis import forms -# Getting the SpatialBackend container and the geographic quoting method. -from django.contrib.gis.db.backend import SpatialBackend, gqn -# GeometryProxy, GEOS, and Distance imports. -from django.contrib.gis.db.models.proxy import GeometryProxy -from django.contrib.gis.measure import Distance - -# Local cache of the spatial_ref_sys table, which holds static data. -# This exists so that we don't have to hit the database each time. -_srid_cache = {} - -def get_srid_info(srid): - """ - Returns the units, unit name, and spheroid WKT associated with the - given SRID from the `spatial_ref_sys` (or equivalent) spatial database - table. These results are cached. - """ - global _srid_cache - - if SpatialBackend.mysql: - return None, None, None - - if not srid in _srid_cache: - from django.contrib.gis.models import SpatialRefSys - sr = SpatialRefSys.objects.get(srid=srid) - units, units_name = sr.units - spheroid = SpatialRefSys.get_spheroid(sr.wkt) - _srid_cache[srid] = (units, units_name, spheroid) - - return _srid_cache[srid] - -class GeometryField(SpatialBackend.Field): - "The base GIS field -- maps to the OpenGIS Specification Geometry type." - - # The OpenGIS Geometry name. - geom_type = 'GEOMETRY' - - # Geodetic units. - geodetic_units = ('Decimal Degree', 'degree') - - def __init__(self, verbose_name=None, srid=4326, spatial_index=True, dim=2, **kwargs): - """ - The initialization function for geometry fields. Takes the following - as keyword arguments: - - srid: - The spatial reference system identifier, an OGC standard. - Defaults to 4326 (WGS84). - - spatial_index: - Indicates whether to create a spatial index. Defaults to True. - Set this instead of 'db_index' for geographic fields since index - creation is different for geometry columns. - - dim: - The number of dimensions for this geometry. Defaults to 2. - """ - - # Setting the index flag with the value of the `spatial_index` keyword. - self.spatial_index = spatial_index - - # Setting the SRID and getting the units. Unit information must be - # easily available in the field instance for distance queries. - self.srid = srid - - # Setting the dimension of the geometry field. - self.dim = dim - - # Setting the verbose_name keyword argument with the positional - # first parameter, so this works like normal fields. - kwargs['verbose_name'] = verbose_name - - super(GeometryField, self).__init__(**kwargs) # Calling the parent initializtion function - - # The following properties are used to get the units, their name, and - # the spheroid corresponding to the SRID of the GeometryField. - def _get_srid_info(self): - # Get attributes from `get_srid_info`. - self._units, self._units_name, self._spheroid = get_srid_info(self.srid) - - @property - def spheroid(self): - if not hasattr(self, '_spheroid'): - self._get_srid_info() - return self._spheroid - - @property - def units(self): - if not hasattr(self, '_units'): - self._get_srid_info() - return self._units - - @property - def units_name(self): - if not hasattr(self, '_units_name'): - self._get_srid_info() - return self._units_name - - # The following properties are for formerly private variables that are now - # public for GeometryField. Because of their use by third-party applications, - # a deprecation warning is issued to notify them to use new attribute name. - def _deprecated_warning(self, old_name, new_name): - from warnings import warn - warn('The `%s` attribute name is deprecated, please update your code to use `%s` instead.' % - (old_name, new_name)) - - @property - def _geom(self): - self._deprecated_warning('_geom', 'geom_type') - return self.geom_type - - @property - def _index(self): - self._deprecated_warning('_index', 'spatial_index') - return self.spatial_index - - @property - def _srid(self): - self._deprecated_warning('_srid', 'srid') - return self.srid - - ### Routines specific to GeometryField ### - @property - def geodetic(self): - """ - Returns true if this field's SRID corresponds with a coordinate - system that uses non-projected units (e.g., latitude/longitude). - """ - return self.units_name in self.geodetic_units - - def get_distance(self, dist_val, lookup_type): - """ - Returns a distance number in units of the field. For example, if - `D(km=1)` was passed in and the units of the field were in meters, - then 1000 would be returned. - """ - # Getting the distance parameter and any options. - if len(dist_val) == 1: dist, option = dist_val[0], None - else: dist, option = dist_val - - if isinstance(dist, Distance): - if self.geodetic: - # Won't allow Distance objects w/DWithin lookups on PostGIS. - if SpatialBackend.postgis and lookup_type == 'dwithin': - raise TypeError('Only numeric values of degree units are allowed on geographic DWithin queries.') - # Spherical distance calculation parameter should be in meters. - dist_param = dist.m - else: - dist_param = getattr(dist, Distance.unit_attname(self.units_name)) - else: - # Assuming the distance is in the units of the field. - dist_param = dist - - if SpatialBackend.postgis and self.geodetic and lookup_type != 'dwithin' and option == 'spheroid': - # On PostGIS, by default `ST_distance_sphere` is used; but if the - # accuracy of `ST_distance_spheroid` is needed than the spheroid - # needs to be passed to the SQL stored procedure. - return [gqn(self._spheroid), dist_param] - else: - return [dist_param] - - def get_geometry(self, value): - """ - Retrieves the geometry, setting the default SRID from the given - lookup parameters. - """ - if isinstance(value, (tuple, list)): - geom = value[0] - else: - geom = value - - # When the input is not a GEOS geometry, attempt to construct one - # from the given string input. - if isinstance(geom, SpatialBackend.Geometry): - pass - elif isinstance(geom, basestring): - try: - geom = SpatialBackend.Geometry(geom) - except SpatialBackend.GeometryException: - raise ValueError('Could not create geometry from lookup value: %s' % str(value)) - else: - raise TypeError('Cannot use parameter of `%s` type as lookup parameter.' % type(value)) - - # Assigning the SRID value. - geom.srid = self.get_srid(geom) - - return geom - - def get_srid(self, geom): - """ - Returns the default SRID for the given geometry, taking into account - the SRID set for the field. For example, if the input geometry - has no SRID, then that of the field will be returned. - """ - gsrid = geom.srid # SRID of given geometry. - if gsrid is None or self.srid == -1 or (gsrid == -1 and self.srid != -1): - return self.srid - else: - return gsrid - - ### Routines overloaded from Field ### - def contribute_to_class(self, cls, name): - super(GeometryField, self).contribute_to_class(cls, name) - - # Setup for lazy-instantiated Geometry object. - setattr(cls, self.attname, GeometryProxy(SpatialBackend.Geometry, self)) - - def formfield(self, **kwargs): - defaults = {'form_class' : forms.GeometryField, - 'null' : self.null, - 'geom_type' : self.geom_type, - 'srid' : self.srid, - } - defaults.update(kwargs) - return super(GeometryField, self).formfield(**defaults) - - def get_db_prep_lookup(self, lookup_type, value): - """ - Returns the spatial WHERE clause and associated parameters for the - given lookup type and value. The value will be prepared for database - lookup (e.g., spatial transformation SQL will be added if necessary). - """ - if lookup_type in SpatialBackend.gis_terms: - # special case for isnull lookup - if lookup_type == 'isnull': return [], [] - - # Get the geometry with SRID; defaults SRID to that of the field - # if it is None. - geom = self.get_geometry(value) - - # Getting the WHERE clause list and the associated params list. The params - # list is populated with the Adaptor wrapping the Geometry for the - # backend. The WHERE clause list contains the placeholder for the adaptor - # (e.g. any transformation SQL). - where = [self.get_placeholder(geom)] - params = [SpatialBackend.Adaptor(geom)] - - if isinstance(value, (tuple, list)): - if lookup_type in SpatialBackend.distance_functions: - # Getting the distance parameter in the units of the field. - where += self.get_distance(value[1:], lookup_type) - elif lookup_type in SpatialBackend.limited_where: - pass - else: - # Otherwise, making sure any other parameters are properly quoted. - where += map(gqn, value[1:]) - return where, params - else: - raise TypeError("Field has invalid lookup: %s" % lookup_type) - - def get_db_prep_save(self, value): - "Prepares the value for saving in the database." - if value is None: - return None - else: - return SpatialBackend.Adaptor(self.get_geometry(value)) - -# The OpenGIS Geometry Type Fields -class PointField(GeometryField): - geom_type = 'POINT' - -class LineStringField(GeometryField): - geom_type = 'LINESTRING' - -class PolygonField(GeometryField): - geom_type = 'POLYGON' - -class MultiPointField(GeometryField): - geom_type = 'MULTIPOINT' - -class MultiLineStringField(GeometryField): - geom_type = 'MULTILINESTRING' - -class MultiPolygonField(GeometryField): - geom_type = 'MULTIPOLYGON' - -class GeometryCollectionField(GeometryField): - geom_type = 'GEOMETRYCOLLECTION'