mirror of https://github.com/django/django.git
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.
|
||||
select = None
|
||||
|
||||
# Does the spatial database have a geography type?
|
||||
# Does the spatial database have a geometry or geography type?
|
||||
geography = False
|
||||
geometry = False
|
||||
|
||||
area = False
|
||||
centroid = False
|
||||
|
|
|
@ -4,7 +4,8 @@ from django.db.backends.postgresql_psycopg2.creation import DatabaseCreation
|
|||
|
||||
class PostGISCreation(DatabaseCreation):
|
||||
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):
|
||||
"Return any spatial index creation SQL for the field."
|
||||
|
@ -17,8 +18,9 @@ class PostGISCreation(DatabaseCreation):
|
|||
qn = self.connection.ops.quote_name
|
||||
db_table = model._meta.db_table
|
||||
|
||||
if f.geography:
|
||||
# Geogrophy columns are created normally.
|
||||
if f.geography or self.connection.ops.geometry:
|
||||
# Geography and Geometry (PostGIS 2.0+) columns are
|
||||
# created normally.
|
||||
pass
|
||||
else:
|
||||
# Geometry columns are created by `AddGeometryColumn`
|
||||
|
@ -47,33 +49,23 @@ class PostGISCreation(DatabaseCreation):
|
|||
# which are fast on multidimensional cases, or just plain
|
||||
# gist index for the 2d case.
|
||||
if f.geography:
|
||||
index_opts = ''
|
||||
elif self.connection.ops.spatial_version >= (2, 0):
|
||||
index_ops = ''
|
||||
elif self.connection.ops.geometry:
|
||||
if f.dim > 2:
|
||||
index_opts = ' ' + style.SQL_KEYWORD('gist_geometry_ops_nd')
|
||||
index_ops = ' ' + style.SQL_KEYWORD(self.geom_index_ops_nd)
|
||||
else:
|
||||
index_opts = ''
|
||||
index_ops = ''
|
||||
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 ') +
|
||||
style.SQL_TABLE(qn('%s_%s_id' % (db_table, f.column))) +
|
||||
style.SQL_KEYWORD(' ON ') +
|
||||
style.SQL_TABLE(qn(db_table)) +
|
||||
style.SQL_KEYWORD(' USING ') +
|
||||
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
|
||||
|
||||
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')
|
||||
|
||||
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 ''
|
||||
return ' TEMPLATE %s' % self.connection.ops.quote_name(postgis_template)
|
||||
|
|
|
@ -103,11 +103,12 @@ class PostGISOperations(DatabaseOperations, BaseSpatialOperations):
|
|||
self.geom_func_prefix = prefix
|
||||
self.spatial_version = version
|
||||
except DatabaseError:
|
||||
raise ImproperlyConfigured('Cannot determine PostGIS version for database "%s". '
|
||||
'GeoDjango requires at least PostGIS version 1.3. '
|
||||
'Was the database created from a spatial database '
|
||||
'template?' % self.connection.settings_dict['NAME']
|
||||
)
|
||||
raise ImproperlyConfigured(
|
||||
'Cannot determine PostGIS version for database "%s". '
|
||||
'GeoDjango requires at least PostGIS version 1.3. '
|
||||
'Was the database created from a spatial database '
|
||||
'template?' % self.connection.settings_dict['NAME']
|
||||
)
|
||||
# TODO: Raise helpful exceptions as they become known.
|
||||
|
||||
# PostGIS-specific operators. The commented descriptions of these
|
||||
|
@ -215,6 +216,10 @@ class PostGISOperations(DatabaseOperations, BaseSpatialOperations):
|
|||
'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.
|
||||
gis_terms = ['isnull']
|
||||
gis_terms += list(self.geometry_operators)
|
||||
|
@ -320,6 +325,14 @@ class PostGISOperations(DatabaseOperations, BaseSpatialOperations):
|
|||
'only with an SRID of 4326.')
|
||||
|
||||
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:
|
||||
return None
|
||||
|
||||
|
|
|
@ -95,7 +95,7 @@ class GeometryField(Field):
|
|||
# Is this a geography rather than a geometry column?
|
||||
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`
|
||||
self._extent = kwargs.pop('extent', (-180.0, -90.0, 180.0, 90.0))
|
||||
self._tolerance = kwargs.pop('tolerance', 0.05)
|
||||
|
|
Loading…
Reference in New Issue