schema.py 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667
  1. from django.db.backends.postgresql_psycopg2.schema import DatabaseSchemaEditor
  2. class PostGISSchemaEditor(DatabaseSchemaEditor):
  3. geom_index_type = 'GIST'
  4. geom_index_ops_nd = 'GIST_GEOMETRY_OPS_ND'
  5. sql_add_spatial_index = "CREATE INDEX %(index)s ON %(table)s USING %(index_type)s (%(column)s %(ops)s)"
  6. sql_clear_geometry_columns = "DELETE FROM geometry_columns WHERE f_table_name = %(table)s"
  7. def __init__(self, *args, **kwargs):
  8. super(PostGISSchemaEditor, self).__init__(*args, **kwargs)
  9. self.geometry_sql = []
  10. def geo_quote_name(self, name):
  11. return self.connection.ops.geo_quote_name(name)
  12. def column_sql(self, model, field, include_default=False):
  13. from django.contrib.gis.db.models.fields import GeometryField
  14. if not isinstance(field, GeometryField):
  15. return super(PostGISSchemaEditor, self).column_sql(model, field, include_default)
  16. column_sql = super(PostGISSchemaEditor, self).column_sql(model, field, include_default)
  17. if field.spatial_index:
  18. # Spatial indexes created the same way for both Geometry and
  19. # Geography columns.
  20. if field.geography:
  21. index_ops = ''
  22. else:
  23. # Use either "nd" ops which are fast on multidimensional cases
  24. # or just plain gist index for the 2d case.
  25. if field.dim > 2:
  26. index_ops = self.geom_index_ops_nd
  27. else:
  28. index_ops = ''
  29. self.geometry_sql.append(
  30. self.sql_add_spatial_index % {
  31. "index": self.quote_name('%s_%s_id' % (model._meta.db_table, field.column)),
  32. "table": self.quote_name(model._meta.db_table),
  33. "column": self.quote_name(field.column),
  34. "index_type": self.geom_index_type,
  35. "ops": index_ops,
  36. }
  37. )
  38. return column_sql
  39. def create_model(self, model):
  40. super(PostGISSchemaEditor, self).create_model(model)
  41. # Create geometry columns
  42. for sql in self.geometry_sql:
  43. self.execute(sql)
  44. self.geometry_sql = []
  45. def delete_model(self, model):
  46. super(PostGISSchemaEditor, self).delete_model(model)
  47. self.execute(self.sql_clear_geometry_columns % {
  48. "table": self.geo_quote_name(model._meta.db_table),
  49. })
  50. def add_field(self, model, field):
  51. super(PostGISSchemaEditor, self).add_field(model, field)
  52. # Create geometry columns
  53. for sql in self.geometry_sql:
  54. self.execute(sql)
  55. self.geometry_sql = []