mirror of
				https://github.com/django/django.git
				synced 2025-10-30 17:16:10 +00:00 
			
		
		
		
	PostGIS schema editor support
This commit is contained in:
		| @@ -3,6 +3,7 @@ from django.db.backends.postgresql_psycopg2.base import DatabaseWrapper as Psyco | |||||||
| from django.contrib.gis.db.backends.postgis.creation import PostGISCreation | from django.contrib.gis.db.backends.postgis.creation import PostGISCreation | ||||||
| from django.contrib.gis.db.backends.postgis.introspection import PostGISIntrospection | from django.contrib.gis.db.backends.postgis.introspection import PostGISIntrospection | ||||||
| from django.contrib.gis.db.backends.postgis.operations import PostGISOperations | from django.contrib.gis.db.backends.postgis.operations import PostGISOperations | ||||||
|  | from django.contrib.gis.db.backends.postgis.schema import PostGISSchemaEditor | ||||||
|  |  | ||||||
|  |  | ||||||
| class DatabaseWrapper(Psycopg2DatabaseWrapper): | class DatabaseWrapper(Psycopg2DatabaseWrapper): | ||||||
| @@ -12,3 +13,7 @@ class DatabaseWrapper(Psycopg2DatabaseWrapper): | |||||||
|             self.creation = PostGISCreation(self) |             self.creation = PostGISCreation(self) | ||||||
|             self.ops = PostGISOperations(self) |             self.ops = PostGISOperations(self) | ||||||
|             self.introspection = PostGISIntrospection(self) |             self.introspection = PostGISIntrospection(self) | ||||||
|  |  | ||||||
|  |     def schema_editor(self, *args, **kwargs): | ||||||
|  |         "Returns a new instance of this backend's SchemaEditor" | ||||||
|  |         return PostGISSchemaEditor(self, *args, **kwargs) | ||||||
|   | |||||||
							
								
								
									
										87
									
								
								django/contrib/gis/db/backends/postgis/schema.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										87
									
								
								django/contrib/gis/db/backends/postgis/schema.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,87 @@ | |||||||
|  | from django.conf import settings | ||||||
|  | from django.db.backends.postgresql_psycopg2.schema import DatabaseSchemaEditor | ||||||
|  | from django.utils.functional import cached_property | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class PostGISSchemaEditor(DatabaseSchemaEditor): | ||||||
|  |     geom_index_type = 'GIST' | ||||||
|  |     geom_index_ops = 'GIST_GEOMETRY_OPS' | ||||||
|  |     geom_index_ops_nd = 'GIST_GEOMETRY_OPS_ND' | ||||||
|  |  | ||||||
|  |     sql_add_geometry_column = "SELECT AddGeometryColumn(%(table)s, %(column)s, %(srid)s, %(geom_type)s, %(dim)s)" | ||||||
|  |     sql_alter_geometry_column_not_null = "ALTER TABLE %(table)s ALTER COLUMN %(column)s SET NOT NULL" | ||||||
|  |     sql_add_spatial_index = "CREATE INDEX %(index)s ON %(table)s USING %(index_type)s (%(column)s %(ops)s)" | ||||||
|  |  | ||||||
|  |     def geo_quote_name(self, name): | ||||||
|  |         return self.connection.ops.geo_quote_name(name) | ||||||
|  |  | ||||||
|  |     def create_model(self, model): | ||||||
|  |         from django.contrib.gis.db.models.fields import GeometryField | ||||||
|  |         # Do model creation first | ||||||
|  |         super(PostGISSchemaEditor, self).create_model(model) | ||||||
|  |         # Now add any spatial field SQL | ||||||
|  |         sqls = [] | ||||||
|  |         for field in model._meta.local_fields: | ||||||
|  |             if isinstance(field, GeometryField): | ||||||
|  |                 sqls.extend(self.spatial_field_sql(model, field)) | ||||||
|  |         for sql in sqls: | ||||||
|  |             self.execute(sql) | ||||||
|  |  | ||||||
|  |     def spatial_field_sql(self, model, field): | ||||||
|  |         """ | ||||||
|  |         Takes a GeometryField and returns a list of SQL to execute to | ||||||
|  |         create its spatial indexes. | ||||||
|  |         """ | ||||||
|  |         output = [] | ||||||
|  |  | ||||||
|  |         if field.geography or self.connection.ops.geometry: | ||||||
|  |             # Geography and Geometry (PostGIS 2.0+) columns are | ||||||
|  |             # created normally. | ||||||
|  |             pass | ||||||
|  |         else: | ||||||
|  |             # Geometry columns are created by the `AddGeometryColumn` | ||||||
|  |             # stored procedure. | ||||||
|  |             output.append( | ||||||
|  |                 self.sql_add_geometry_column % { | ||||||
|  |                     "table": self.geo_quote_name(model._meta.db_table), | ||||||
|  |                     "column": self.geo_quote_name(field.column), | ||||||
|  |                     "srid": field.srid, | ||||||
|  |                     "geom_type": self.geo_quote_name(field.geom_type), | ||||||
|  |                     "dim": field.dim, | ||||||
|  |                 } | ||||||
|  |             ) | ||||||
|  |             if not field.null: | ||||||
|  |                 output.append( | ||||||
|  |                     self.sql_alter_geometry_column_not_null % { | ||||||
|  |                         "table": self.quote_name(model._meta.db_table), | ||||||
|  |                         "column": self.quote_name(field.column), | ||||||
|  |                     }, | ||||||
|  |                 ) | ||||||
|  |  | ||||||
|  |         if field.spatial_index: | ||||||
|  |             # Spatial indexes created the same way for both Geometry and | ||||||
|  |             # Geography columns. | ||||||
|  |             # PostGIS 2.0 does not support GIST_GEOMETRY_OPS. So, on 1.5 | ||||||
|  |             # we use GIST_GEOMETRY_OPS, on 2.0 we use either "nd" ops | ||||||
|  |             # which are fast on multidimensional cases, or just plain | ||||||
|  |             # gist index for the 2d case. | ||||||
|  |             if field.geography: | ||||||
|  |                 index_ops = '' | ||||||
|  |             elif self.connection.ops.geometry: | ||||||
|  |                 if field.dim > 2: | ||||||
|  |                     index_ops = self.geom_index_ops_nd | ||||||
|  |                 else: | ||||||
|  |                     index_ops = '' | ||||||
|  |             else: | ||||||
|  |                 index_ops = self.geom_index_ops | ||||||
|  |             output.append( | ||||||
|  |                 self.sql_add_spatial_index % { | ||||||
|  |                     "index": self.quote_name('%s_%s_id' % (model._meta.db_table, field.column)), | ||||||
|  |                     "table": self.quote_name(model._meta.db_table), | ||||||
|  |                     "column": self.quote_name(field.column), | ||||||
|  |                     "index_type": self.geom_index_type, | ||||||
|  |                     "ops": index_ops, | ||||||
|  |                 } | ||||||
|  |             ) | ||||||
|  |  | ||||||
|  |         return output | ||||||
		Reference in New Issue
	
	Block a user