1
0
mirror of https://github.com/django/django.git synced 2025-07-04 17:59:13 +00:00

gis: NULL geometries are now allowed (thanks Robert Coup!), field parameter no longer needed for _post_create_sql(), and added extra instance methods for SpatialReference/SRID.

git-svn-id: http://code.djangoproject.com/svn/django/branches/gis@5448 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Justin Bronn 2007-06-09 19:55:42 +00:00
parent b962a44a4d
commit 6538a26a47
3 changed files with 39 additions and 20 deletions

View File

@ -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 # Until model subclassing is a possibility, a mixin class is used to add
# the necessary functions that may be contributed for geographic objects. # the necessary functions that may be contributed for geographic objects.
class GeoMixin: 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 # A subclass of Model is specifically needed so that these geographic
# routines are present for instantiations of the models. # routines are present for instantiations of the models.
def _get_GEOM_geos(self, field): 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') return GEOSGeometry(getattr(self, field.attname), 'hex')
def _get_GEOM_ogr(self, field, srid): 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)), return OGRGeometry(hex_to_wkt(getattr(self, field.attname)),
SpatialReference('EPSG:%d' % srid)) 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): def _get_GEOM_wkt(self, field):
"Gets the WKT of the geometry." "Returns the WKT of the geometry."
hex = getattr(self, field.attname) hex = getattr(self, field.attname)
return hex_to_wkt(hex) return hex_to_wkt(hex)
def _get_GEOM_centroid(self, field): 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) hex = getattr(self, field.attname)
return centroid(hex) return centroid(hex)
def _get_GEOM_area(self, field): 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) hex = getattr(self, field.attname)
return area(hex) return area(hex)

View File

@ -33,47 +33,56 @@ class GeometryField(Field):
self._dim = dim self._dim = dim
super(GeometryField, self).__init__(**kwargs) # Calling the parent initializtion function 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 """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 Takes the style object (provides syntax highlighting) and the
database table and field. database table as parameters.
""" """
sql = style.SQL_KEYWORD('SELECT ') + \ sql = style.SQL_KEYWORD('SELECT ') + \
style.SQL_TABLE('AddGeometryColumn') + '(' + \ style.SQL_TABLE('AddGeometryColumn') + '(' + \
style.SQL_TABLE(quotename(db_table)) + ', ' + \ 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_FIELD(str(self._srid)) + ', ' + \
style.SQL_COLTYPE(quotename(self._geom)) + ', ' + \ style.SQL_COLTYPE(quotename(self._geom)) + ', ' + \
style.SQL_KEYWORD(str(self._dim)) + ');' 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 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'): index_type='GIST', index_opts='GIST_GEOMETRY_OPS'):
"Creates a GiST index for this geometry field." "Creates a GiST index for this geometry field."
sql = style.SQL_KEYWORD('CREATE INDEX ') + \ 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_KEYWORD(' ON ') + \
style.SQL_TABLE(quotename(db_table, dbl=True)) + \ style.SQL_TABLE(quotename(db_table, dbl=True)) + \
style.SQL_KEYWORD(' USING ') + \ style.SQL_KEYWORD(' USING ') + \
style.SQL_COLTYPE(index_type) + ' ( ' + \ 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) + ' );' style.SQL_KEYWORD(index_opts) + ' );'
return sql 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 """Returns SQL that will be executed after the model has been
created. Geometry columns must be added after creation with the created. Geometry columns must be added after creation with the
PostGIS AddGeometryColumn() function.""" PostGIS AddGeometryColumn() function."""
# Getting the AddGeometryColumn() SQL necessary to create a PostGIS # Getting the AddGeometryColumn() SQL necessary to create a PostGIS
# geometry field. # 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 the user wants to index this data, then get the indexing SQL as well.
if self._index: 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: else:
return post_sql return post_sql
@ -83,6 +92,8 @@ class GeometryField(Field):
# Adding needed accessor functions # Adding needed accessor functions
setattr(cls, 'get_%s_geos' % self.name, curry(cls._get_GEOM_geos, field=self)) 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_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_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_centroid' % self.name, curry(cls._get_GEOM_centroid, field=self))
setattr(cls, 'get_%s_area' % self.name, curry(cls._get_GEOM_area, 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 """Returns field's value prepared for database lookup; the SRID of the geometry is
included by default in these queries.""" included by default in these queries."""
if lookup_type in POSTGIS_TERMS: 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) raise TypeError("Field has invalid lookup: %s" % lookup_type)
def get_db_prep_save(self, value): def get_db_prep_save(self, value):
"Making sure the SRID is included before saving." "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): def get_manipulator_field_objs(self):
"Using the WKTField (defined above) to be our manipulator." "Using the WKTField (defined above) to be our manipulator."

View File

@ -388,7 +388,7 @@ def get_custom_sql_for_model(model):
for f in opts.fields: for f in opts.fields:
if hasattr(f, '_post_create_sql'): 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 return output