diff --git a/django/contrib/gis/db/models/__init__.py b/django/contrib/gis/db/models/__init__.py index ef166e52a6..2d19fe9028 100644 --- a/django/contrib/gis/db/models/__init__.py +++ b/django/contrib/gis/db/models/__init__.py @@ -14,4 +14,4 @@ from django.contrib.gis.db.models.fields import \ GeometryCollectionField # The geographic mixin class. -from GeoMixin import GeoMixin +from mixin import GeoMixin diff --git a/django/contrib/gis/db/models/fields/__init__.py b/django/contrib/gis/db/models/fields/__init__.py index f01c40bfe8..41d26c58b8 100644 --- a/django/contrib/gis/db/models/fields/__init__.py +++ b/django/contrib/gis/db/models/fields/__init__.py @@ -1,5 +1,6 @@ # The Django base Field class. from django.db.models.fields import Field +from django.contrib.gis.db.models.proxy import GeometryProxy from django.contrib.gis.db.models.postgis import POSTGIS_TERMS, quotename from django.contrib.gis.oldforms import WKTField from django.utils.functional import curry @@ -86,9 +87,20 @@ class GeometryField(Field): else: return post_sql + def _post_delete_sql(self, style, db_table): + "Drops the geometry column." + sql = style.SQL_KEYWORD('SELECT ') + \ + style.SQL_KEYWORD('DropGeometryColumn') + '(' + \ + style.SQL_TABLE(quotename(db_table)) + ', ' + \ + style.SQL_FIELD(quotename(self.column)) + ');' + return sql + def contribute_to_class(self, cls, name): super(GeometryField, self).contribute_to_class(cls, name) + # setup for lazy-instantiated GEOSGeometry objects + setattr(cls, self.attname, GeometryProxy(self)) + # Adding needed accessor functions setattr(cls, 'get_%s_geos' % self.name, curry(cls._get_GEOM_geos, field=self)) setattr(cls, 'get_%s_ogr' % self.name, curry(cls._get_GEOM_ogr, field=self, srid=self._srid)) diff --git a/django/contrib/gis/db/models/GeoMixin.py b/django/contrib/gis/db/models/mixin.py similarity index 71% rename from django/contrib/gis/db/models/GeoMixin.py rename to django/contrib/gis/db/models/mixin.py index c66110dc15..8077d3d743 100644 --- a/django/contrib/gis/db/models/GeoMixin.py +++ b/django/contrib/gis/db/models/mixin.py @@ -1,4 +1,5 @@ # GEOS Routines +from warnings import warn from django.contrib.gis.geos import GEOSGeometry, hex_to_wkt, centroid, area from django.contrib.gis.gdal import OGRGeometry, SpatialReference @@ -11,7 +12,8 @@ class GeoMixin: # routines are present for instantiations of the models. def _get_GEOM_geos(self, field): "Returns a GEOS Python object for the geometry." - return GEOSGeometry(getattr(self, field.attname), 'hex') + warn("use model.%s" % field.attname, DeprecationWarning) + return getattr(self, field.attname) def _get_GEOM_ogr(self, field, srid): "Returns an OGR Python object for the geometry." @@ -20,6 +22,7 @@ class GeoMixin: def _get_GEOM_srid(self, srid): "Returns the spatial reference identifier (SRID) of the geometry." + warn("use model.geometry_field.srid", DeprecationWarning) return srid def _get_GEOM_srs(self, srid): @@ -28,17 +31,17 @@ class GeoMixin: def _get_GEOM_wkt(self, field): "Returns the WKT of the geometry." - hex = getattr(self, field.attname) - return hex_to_wkt(hex) + warn("use model.%s.centroid.wkt" % field.attname, DeprecationWarning) + return getattr(self, field.attname).wkt def _get_GEOM_centroid(self, field): "Returns the centroid of the geometry, in WKT." - hex = getattr(self, field.attname) - return centroid(hex) + warn("use model.%s.centroid.wkt" % field.attname, DeprecationWarning) + return getattr(self, field.attname).centroid.wkt def _get_GEOM_area(self, field): "Returns the area of the geometry, in projected units." - hex = getattr(self, field.attname) - return area(hex) + warn("use model.%s.area" % field.attname, DeprecationWarning) + return getattr(self, field.attname).area diff --git a/django/contrib/gis/db/models/postgis.py b/django/contrib/gis/db/models/postgis.py index b147b89531..776181624c 100644 --- a/django/contrib/gis/db/models/postgis.py +++ b/django/contrib/gis/db/models/postgis.py @@ -38,7 +38,7 @@ POSTGIS_OPERATORS = { # PostGIS Geometry Functions -- most of these use GEOS. POSTGIS_GEOMETRY_FUNCTIONS = { - 'distance' : 'Distance', + #'distance' : 'Distance', -- doesn't work right now. 'equals' : 'Equals', 'disjoint' : 'Disjoint', 'touches' : 'Touches', diff --git a/django/contrib/gis/db/models/proxy.py b/django/contrib/gis/db/models/proxy.py new file mode 100644 index 0000000000..4762e8b18f --- /dev/null +++ b/django/contrib/gis/db/models/proxy.py @@ -0,0 +1,30 @@ +""" + The GeometryProxy object, allows for lazy-geometries. + + Thanks to Robert Coup for providing this functionality (see #4322). +""" + +# GEOS Routines +from django.contrib.gis.geos import GEOSGeometry, GEOSException + +# TODO: docstrings & comments +class GeometryProxy(object): + def __init__(self, field): + self._field = field + + def __get__(self, obj, type=None): + geom_value = obj.__dict__[self._field.attname] + if (geom_value is None) or (isinstance(geom_value, GEOSGeometry)): + geom = geom_value + else: + geom = GEOSGeometry(geom_value) + setattr(obj, self._field.attname, geom) + return geom + + def __set__(self, obj, value): + if isinstance(value, GEOSGeometry): + if value and ((value.srid is None) and (self._field._srid is not None)): + value.set_srid(self._field._srid) + + obj.__dict__[self._field.attname] = value + return value