Use native geometry types on PostGIS 2.0+ instead of `AddGeometryColumn` and don't query database in `PostGISCreation.sql_table_creation_suffix`.
This commit is contained in:
parent
b6b8a3f66b
commit
91ef2a5253
|
@ -32,8 +32,9 @@ class BaseSpatialOperations(object):
|
||||||
# How the geometry column should be selected.
|
# How the geometry column should be selected.
|
||||||
select = None
|
select = None
|
||||||
|
|
||||||
# Does the spatial database have a geography type?
|
# Does the spatial database have a geometry or geography type?
|
||||||
geography = False
|
geography = False
|
||||||
|
geometry = False
|
||||||
|
|
||||||
area = False
|
area = False
|
||||||
centroid = False
|
centroid = False
|
||||||
|
|
|
@ -4,7 +4,8 @@ from django.db.backends.postgresql_psycopg2.creation import DatabaseCreation
|
||||||
|
|
||||||
class PostGISCreation(DatabaseCreation):
|
class PostGISCreation(DatabaseCreation):
|
||||||
geom_index_type = 'GIST'
|
geom_index_type = 'GIST'
|
||||||
geom_index_opts = 'GIST_GEOMETRY_OPS'
|
geom_index_ops = 'GIST_GEOMETRY_OPS'
|
||||||
|
geom_index_ops_nd = 'GIST_GEOMETRY_OPS_ND'
|
||||||
|
|
||||||
def sql_indexes_for_field(self, model, f, style):
|
def sql_indexes_for_field(self, model, f, style):
|
||||||
"Return any spatial index creation SQL for the field."
|
"Return any spatial index creation SQL for the field."
|
||||||
|
@ -17,8 +18,9 @@ class PostGISCreation(DatabaseCreation):
|
||||||
qn = self.connection.ops.quote_name
|
qn = self.connection.ops.quote_name
|
||||||
db_table = model._meta.db_table
|
db_table = model._meta.db_table
|
||||||
|
|
||||||
if f.geography:
|
if f.geography or self.connection.ops.geometry:
|
||||||
# Geogrophy columns are created normally.
|
# Geography and Geometry (PostGIS 2.0+) columns are
|
||||||
|
# created normally.
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
# Geometry columns are created by `AddGeometryColumn`
|
# Geometry columns are created by `AddGeometryColumn`
|
||||||
|
@ -47,33 +49,23 @@ class PostGISCreation(DatabaseCreation):
|
||||||
# which are fast on multidimensional cases, or just plain
|
# which are fast on multidimensional cases, or just plain
|
||||||
# gist index for the 2d case.
|
# gist index for the 2d case.
|
||||||
if f.geography:
|
if f.geography:
|
||||||
index_opts = ''
|
index_ops = ''
|
||||||
elif self.connection.ops.spatial_version >= (2, 0):
|
elif self.connection.ops.geometry:
|
||||||
if f.dim > 2:
|
if f.dim > 2:
|
||||||
index_opts = ' ' + style.SQL_KEYWORD('gist_geometry_ops_nd')
|
index_ops = ' ' + style.SQL_KEYWORD(self.geom_index_ops_nd)
|
||||||
else:
|
else:
|
||||||
index_opts = ''
|
index_ops = ''
|
||||||
else:
|
else:
|
||||||
index_opts = ' ' + style.SQL_KEYWORD(self.geom_index_opts)
|
index_ops = ' ' + style.SQL_KEYWORD(self.geom_index_ops)
|
||||||
output.append(style.SQL_KEYWORD('CREATE INDEX ') +
|
output.append(style.SQL_KEYWORD('CREATE INDEX ') +
|
||||||
style.SQL_TABLE(qn('%s_%s_id' % (db_table, f.column))) +
|
style.SQL_TABLE(qn('%s_%s_id' % (db_table, f.column))) +
|
||||||
style.SQL_KEYWORD(' ON ') +
|
style.SQL_KEYWORD(' ON ') +
|
||||||
style.SQL_TABLE(qn(db_table)) +
|
style.SQL_TABLE(qn(db_table)) +
|
||||||
style.SQL_KEYWORD(' USING ') +
|
style.SQL_KEYWORD(' USING ') +
|
||||||
style.SQL_COLTYPE(self.geom_index_type) + ' ( ' +
|
style.SQL_COLTYPE(self.geom_index_type) + ' ( ' +
|
||||||
style.SQL_FIELD(qn(f.column)) + index_opts + ' );')
|
style.SQL_FIELD(qn(f.column)) + index_ops + ' );')
|
||||||
return output
|
return output
|
||||||
|
|
||||||
def sql_table_creation_suffix(self):
|
def sql_table_creation_suffix(self):
|
||||||
cursor = self.connection.cursor()
|
|
||||||
cursor.execute('SELECT datname FROM pg_database;')
|
|
||||||
db_names = [row[0] for row in cursor.fetchall()]
|
|
||||||
postgis_template = getattr(settings, 'POSTGIS_TEMPLATE', 'template_postgis')
|
postgis_template = getattr(settings, 'POSTGIS_TEMPLATE', 'template_postgis')
|
||||||
|
return ' TEMPLATE %s' % self.connection.ops.quote_name(postgis_template)
|
||||||
if postgis_template in db_names:
|
|
||||||
qn = self.connection.ops.quote_name
|
|
||||||
return ' TEMPLATE %s' % qn(postgis_template)
|
|
||||||
elif self.connection.ops.spatial_version < (2, 0):
|
|
||||||
raise ImproperlyConfigured("Template database '%s' does not exist." % postgis_template)
|
|
||||||
else:
|
|
||||||
return ''
|
|
||||||
|
|
|
@ -103,7 +103,8 @@ class PostGISOperations(DatabaseOperations, BaseSpatialOperations):
|
||||||
self.geom_func_prefix = prefix
|
self.geom_func_prefix = prefix
|
||||||
self.spatial_version = version
|
self.spatial_version = version
|
||||||
except DatabaseError:
|
except DatabaseError:
|
||||||
raise ImproperlyConfigured('Cannot determine PostGIS version for database "%s". '
|
raise ImproperlyConfigured(
|
||||||
|
'Cannot determine PostGIS version for database "%s". '
|
||||||
'GeoDjango requires at least PostGIS version 1.3. '
|
'GeoDjango requires at least PostGIS version 1.3. '
|
||||||
'Was the database created from a spatial database '
|
'Was the database created from a spatial database '
|
||||||
'template?' % self.connection.settings_dict['NAME']
|
'template?' % self.connection.settings_dict['NAME']
|
||||||
|
@ -215,6 +216,10 @@ class PostGISOperations(DatabaseOperations, BaseSpatialOperations):
|
||||||
'bboverlaps' : PostGISOperator('&&'),
|
'bboverlaps' : PostGISOperator('&&'),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Native geometry type support added in PostGIS 2.0.
|
||||||
|
if version >= (2, 0, 0):
|
||||||
|
self.geometry = True
|
||||||
|
|
||||||
# Creating a dictionary lookup of all GIS terms for PostGIS.
|
# Creating a dictionary lookup of all GIS terms for PostGIS.
|
||||||
gis_terms = ['isnull']
|
gis_terms = ['isnull']
|
||||||
gis_terms += list(self.geometry_operators)
|
gis_terms += list(self.geometry_operators)
|
||||||
|
@ -320,6 +325,14 @@ class PostGISOperations(DatabaseOperations, BaseSpatialOperations):
|
||||||
'only with an SRID of 4326.')
|
'only with an SRID of 4326.')
|
||||||
|
|
||||||
return 'geography(%s,%d)'% (f.geom_type, f.srid)
|
return 'geography(%s,%d)'% (f.geom_type, f.srid)
|
||||||
|
elif self.geometry:
|
||||||
|
# Postgis 2.0 supports type-based geometries.
|
||||||
|
# TODO: Support 'M' extension.
|
||||||
|
if f.dim == 3:
|
||||||
|
geom_type = f.geom_type + 'Z'
|
||||||
|
else:
|
||||||
|
geom_type = f.geom_type
|
||||||
|
return 'geometry(%s,%d)' % (geom_type, f.srid)
|
||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
|
@ -95,7 +95,7 @@ class GeometryField(Field):
|
||||||
# Is this a geography rather than a geometry column?
|
# Is this a geography rather than a geometry column?
|
||||||
self.geography = geography
|
self.geography = geography
|
||||||
|
|
||||||
# Oracle-specific private attributes for creating the entrie in
|
# Oracle-specific private attributes for creating the entry in
|
||||||
# `USER_SDO_GEOM_METADATA`
|
# `USER_SDO_GEOM_METADATA`
|
||||||
self._extent = kwargs.pop('extent', (-180.0, -90.0, 180.0, 90.0))
|
self._extent = kwargs.pop('extent', (-180.0, -90.0, 180.0, 90.0))
|
||||||
self._tolerance = kwargs.pop('tolerance', 0.05)
|
self._tolerance = kwargs.pop('tolerance', 0.05)
|
||||||
|
|
Loading…
Reference in New Issue