diff --git a/django/contrib/gis/db/models/GeoMixin.py b/django/contrib/gis/db/models/GeoMixin.py index af40aac4ff..c66110dc15 100644 --- a/django/contrib/gis/db/models/GeoMixin.py +++ b/django/contrib/gis/db/models/GeoMixin.py @@ -5,31 +5,39 @@ from django.contrib.gis.gdal import OGRGeometry, SpatialReference # Until model subclassing is a possibility, a mixin class is used to add # the necessary functions that may be contributed for geographic objects. class GeoMixin: - "The Geographic Mixin class, provides routines for geographic objects." + "The Geographic Mixin class provides routines for geographic objects." # A subclass of Model is specifically needed so that these geographic # routines are present for instantiations of the models. def _get_GEOM_geos(self, field): - "Gets a GEOS Python object for the geometry." + "Returns a GEOS Python object for the geometry." return GEOSGeometry(getattr(self, field.attname), 'hex') def _get_GEOM_ogr(self, field, srid): - "Gets an OGR Python object for the geometry." + "Returns an OGR Python object for the geometry." return OGRGeometry(hex_to_wkt(getattr(self, field.attname)), SpatialReference('EPSG:%d' % srid)) + def _get_GEOM_srid(self, srid): + "Returns the spatial reference identifier (SRID) of the geometry." + return srid + + def _get_GEOM_srs(self, srid): + "Returns ane OGR Spatial Reference object of the geometry." + return SpatialReference('EPSG:%d' % srid) + def _get_GEOM_wkt(self, field): - "Gets the WKT of the geometry." + "Returns the WKT of the geometry." hex = getattr(self, field.attname) return hex_to_wkt(hex) def _get_GEOM_centroid(self, field): - "Gets the centroid of the geometry, in WKT." + "Returns the centroid of the geometry, in WKT." hex = getattr(self, field.attname) return centroid(hex) def _get_GEOM_area(self, field): - "Gets the area of the geometry, in projected units." + "Returns the area of the geometry, in projected units." hex = getattr(self, field.attname) return area(hex) diff --git a/django/contrib/gis/db/models/fields/__init__.py b/django/contrib/gis/db/models/fields/__init__.py index d392b62f42..f01c40bfe8 100644 --- a/django/contrib/gis/db/models/fields/__init__.py +++ b/django/contrib/gis/db/models/fields/__init__.py @@ -33,47 +33,56 @@ class GeometryField(Field): self._dim = dim super(GeometryField, self).__init__(**kwargs) # Calling the parent initializtion function - def _add_geom(self, style, db_table, field): + def _add_geom(self, style, db_table): """Constructs the addition of the geometry to the table using the - AddGeometryColumn(...) PostGIS (and OGC standard) function. + AddGeometryColumn(...) PostGIS (and OGC standard) stored procedure. - Takes the style object (provides syntax highlighting) as well as the - database table and field. + Takes the style object (provides syntax highlighting) and the + database table as parameters. """ sql = style.SQL_KEYWORD('SELECT ') + \ style.SQL_TABLE('AddGeometryColumn') + '(' + \ style.SQL_TABLE(quotename(db_table)) + ', ' + \ - style.SQL_FIELD(quotename(field)) + ', ' + \ + style.SQL_FIELD(quotename(self.column)) + ', ' + \ style.SQL_FIELD(str(self._srid)) + ', ' + \ style.SQL_COLTYPE(quotename(self._geom)) + ', ' + \ style.SQL_KEYWORD(str(self._dim)) + ');' + + if not self.null: + # Add a NOT NULL constraint to the field + sql += '\n' + \ + style.SQL_KEYWORD('ALTER TABLE ') + \ + style.SQL_TABLE(quotename(db_table, dbl=True)) + \ + style.SQL_KEYWORD(' ALTER ') + \ + style.SQL_FIELD(quotename(self.column, dbl=True)) + \ + style.SQL_KEYWORD(' SET NOT NULL') + ';' return sql - def _geom_index(self, style, db_table, field, + def _geom_index(self, style, db_table, index_type='GIST', index_opts='GIST_GEOMETRY_OPS'): "Creates a GiST index for this geometry field." sql = style.SQL_KEYWORD('CREATE INDEX ') + \ - style.SQL_TABLE(quotename('%s_%s_id' % (db_table, field), dbl=True)) + \ + style.SQL_TABLE(quotename('%s_%s_id' % (db_table, self.column), dbl=True)) + \ style.SQL_KEYWORD(' ON ') + \ style.SQL_TABLE(quotename(db_table, dbl=True)) + \ style.SQL_KEYWORD(' USING ') + \ style.SQL_COLTYPE(index_type) + ' ( ' + \ - style.SQL_FIELD(quotename(field, dbl=True)) + ' ' + \ + style.SQL_FIELD(quotename(self.column, dbl=True)) + ' ' + \ style.SQL_KEYWORD(index_opts) + ' );' return sql - def _post_create_sql(self, style, db_table, field): + def _post_create_sql(self, style, db_table): """Returns SQL that will be executed after the model has been created. Geometry columns must be added after creation with the PostGIS AddGeometryColumn() function.""" # Getting the AddGeometryColumn() SQL necessary to create a PostGIS # geometry field. - post_sql = self._add_geom(style, db_table, field) + post_sql = self._add_geom(style, db_table) # If the user wants to index this data, then get the indexing SQL as well. if self._index: - return '%s\n%s' % (post_sql, self._geom_index(style, db_table, field)) + return '%s\n%s' % (post_sql, self._geom_index(style, db_table)) else: return post_sql @@ -83,6 +92,8 @@ class GeometryField(Field): # 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)) + setattr(cls, 'get_%s_srid' % self.name, curry(cls._get_GEOM_srid, srid=self._srid)) + setattr(cls, 'get_%s_srs' % self.name, curry(cls._get_GEOM_srs, srid=self._srid)) setattr(cls, 'get_%s_wkt' % self.name, curry(cls._get_GEOM_wkt, field=self)) setattr(cls, 'get_%s_centroid' % self.name, curry(cls._get_GEOM_centroid, field=self)) setattr(cls, 'get_%s_area' % self.name, curry(cls._get_GEOM_area, field=self)) @@ -94,12 +105,12 @@ class GeometryField(Field): """Returns field's value prepared for database lookup; the SRID of the geometry is included by default in these queries.""" if lookup_type in POSTGIS_TERMS: - return ['SRID=%d;%s' % (self._srid, value)] + return [value and ("SRID=%d;%s" % (self._srid, value)) or None] raise TypeError("Field has invalid lookup: %s" % lookup_type) def get_db_prep_save(self, value): "Making sure the SRID is included before saving." - return 'SRID=%d;%s' % (self._srid, value) + return value and ("SRID=%d;%s" % (self._srid, value)) or None def get_manipulator_field_objs(self): "Using the WKTField (defined above) to be our manipulator." diff --git a/django/core/management.py b/django/core/management.py index 485165613c..796e8cc36b 100644 --- a/django/core/management.py +++ b/django/core/management.py @@ -388,7 +388,7 @@ def get_custom_sql_for_model(model): for f in opts.fields: if hasattr(f, '_post_create_sql'): - output.append(f._post_create_sql(style, model._meta.db_table, f.column)) + output.append(f._post_create_sql(style, model._meta.db_table)) return output