| 6 | | |
|---|
| 7 | | #TODO: add db.quotename. |
|---|
| 8 | | |
|---|
| 9 | | # Creates the SQL to add the model to the database. |
|---|
| 10 | | def _add_geom(geom, srid, style, model, field, dim=2): |
|---|
| 11 | | # Constructing the AddGeometryColumn(...) command -- the style |
|---|
| 12 | | # object is passed in from the management module and is used |
|---|
| 13 | | # to syntax highlight the command for 'sqlall' |
|---|
| 14 | | sql = style.SQL_KEYWORD('SELECT ') + \ |
|---|
| 15 | | style.SQL_TABLE('AddGeometryColumn') + "('" + \ |
|---|
| 16 | | style.SQL_TABLE(model) + "', '" + \ |
|---|
| 17 | | style.SQL_FIELD(field) + "', " + \ |
|---|
| 18 | | style.SQL_FIELD(str(srid)) + ", '" + \ |
|---|
| 19 | | style.SQL_COLTYPE(geom) + "', " + \ |
|---|
| 20 | | style.SQL_KEYWORD(str(dim)) + \ |
|---|
| 21 | | ');' |
|---|
| 22 | | return sql |
|---|
| 23 | | |
|---|
| 24 | | # Creates an index for the given geometry. |
|---|
| 25 | | def _geom_index(geom, style, model, field, |
|---|
| 26 | | index_type='GIST', |
|---|
| 27 | | index_opts='GIST_GEOMETRY_OPS'): |
|---|
| 28 | | sql = style.SQL_KEYWORD('CREATE INDEX ') + \ |
|---|
| 29 | | style.SQL_TABLE('"%s_%s_id"' % (model, field)) + \ |
|---|
| 30 | | style.SQL_KEYWORD(' ON ') + \ |
|---|
| 31 | | style.SQL_TABLE('"%s"' % model) + \ |
|---|
| 32 | | style.SQL_KEYWORD(' USING ') + \ |
|---|
| 33 | | style.SQL_COLTYPE(index_type) + ' ( ' + \ |
|---|
| 34 | | style.SQL_FIELD('"%s"' % field) + ' ' + \ |
|---|
| 35 | | style.SQL_KEYWORD(index_opts) + ' );' |
|---|
| 36 | | return sql |
|---|
| | 6 | from django.contrib.gis.geos import GEOSGeometry, GEOSException |
|---|
| 44 | | def __init__(self, srid=4326, index=False, **kwargs): |
|---|
| 45 | | #TODO: SRID a standard, or specific to postgis? |
|---|
| 46 | | # Whether or not index this field, defaults to False |
|---|
| 47 | | # Why can't we just use db_index? |
|---|
| 48 | | # TODO: Move index creation (and kwarg lookup, and...) |
|---|
| 49 | | # into Field rather than core.management and db.models.query. |
|---|
| | 14 | def __init__(self, srid=4326, index=True, dim=2, **kwargs): |
|---|
| | 15 | """The initialization function for geometry fields. Takes the following |
|---|
| | 16 | as keyword arguments: |
|---|
| | 17 | |
|---|
| | 18 | srid - The spatial reference system identifier. An OGC standard. |
|---|
| | 19 | Defaults to 4326 (WGS84) |
|---|
| | 20 | |
|---|
| | 21 | index - Indicates whether to create a GiST index. Defaults to True. |
|---|
| | 22 | Set this instead of 'db_index' for geographic fields since index |
|---|
| | 23 | creation is different for geometry columns. |
|---|
| | 24 | |
|---|
| | 25 | dim - The number of dimensions for this geometry. Defaults to 2. |
|---|
| | 26 | """ |
|---|
| 55 | | # Calling the Field initialization function first |
|---|
| 56 | | super(GeometryField, self).__init__(**kwargs) |
|---|
| | 36 | Takes the style object (provides syntax highlighting) as well as the |
|---|
| | 37 | database table and field. The dimensions can be specified via |
|---|
| | 38 | the dim keyword as well. |
|---|
| | 39 | """ |
|---|
| | 40 | sql = style.SQL_KEYWORD('SELECT ') + \ |
|---|
| | 41 | style.SQL_TABLE('AddGeometryColumn') + '(' + \ |
|---|
| | 42 | style.SQL_TABLE(quotename(db_table)) + ', ' + \ |
|---|
| | 43 | style.SQL_FIELD(quotename(field)) + ', ' + \ |
|---|
| | 44 | style.SQL_FIELD(str(self._srid)) + ', ' + \ |
|---|
| | 45 | style.SQL_COLTYPE(quotename(self._geom)) + ', ' + \ |
|---|
| | 46 | style.SQL_KEYWORD(str(self._dim)) + ');' |
|---|
| | 47 | return sql |
|---|
| | 49 | def _geom_index(self, style, db_table, field, |
|---|
| | 50 | index_type='GIST', index_opts='GIST_GEOMETRY_OPS'): |
|---|
| | 51 | "Creates a GiST index for this geometry field." |
|---|
| | 52 | sql = style.SQL_KEYWORD('CREATE INDEX ') + \ |
|---|
| | 53 | style.SQL_TABLE(quotename('%s_%s_id' % (db_table, field), dbl=True)) + \ |
|---|
| | 54 | style.SQL_KEYWORD(' ON ') + \ |
|---|
| | 55 | style.SQL_TABLE(quotename(db_table, dbl=True)) + \ |
|---|
| | 56 | style.SQL_KEYWORD(' USING ') + \ |
|---|
| | 57 | style.SQL_COLTYPE(index_type) + ' ( ' + \ |
|---|
| | 58 | style.SQL_FIELD(quotename(field, dbl=True)) + ' ' + \ |
|---|
| | 59 | style.SQL_KEYWORD(index_opts) + ' );' |
|---|
| | 60 | return sql |
|---|
| | 61 | |
|---|
| | 62 | def _post_create_sql(self, style, db_table, field): |
|---|
| | 63 | """Returns SQL that will be executed after the model has been |
|---|
| | 64 | created. Geometry columns must be added after creation with the |
|---|
| | 65 | PostGIS AddGeometryColumn() function.""" |
|---|
| | 66 | |
|---|
| | 67 | # Getting the AddGeometryColumn() SQL necessary to create a PostGIS |
|---|
| | 68 | # geometry field. |
|---|
| | 69 | post_sql = self._add_geom(style, db_table, field) |
|---|
| | 70 | |
|---|
| | 71 | # If the user wants to index this data, then get the indexing SQL as well. |
|---|
| | 72 | if self._index: |
|---|
| | 73 | return '%s\n%s' % (post_sql, self._geom_index(style, db_table, field)) |
|---|
| | 74 | else: |
|---|
| | 75 | return post_sql |
|---|
| 70 | | |
|---|
| 71 | | def _post_create_sql(self, *args, **kwargs): |
|---|
| 72 | | """Returns SQL that will be executed after the model has been created. Geometry |
|---|
| 73 | | columns must be added after creation with the PostGIS AddGeometryColumn() function.""" |
|---|
| 74 | | |
|---|
| 75 | | #TODO: clean up *args/**kwargs. |
|---|
| 76 | | |
|---|
| 77 | | # Getting the AddGeometryColumn() SQL necessary to create a PostGIS |
|---|
| 78 | | # geometry field. |
|---|
| 79 | | post_sql = _add_geom(self._geom, self._srid, *args, **kwargs) |
|---|
| 80 | | |
|---|
| 81 | | # If the user wants to index this data, then get the indexing SQL as well. |
|---|
| 82 | | if self._index: |
|---|
| 83 | | return '%s\n%s' % (post_sql, _geom_index(self._geom, *args, **kwargs)) |
|---|
| 84 | | else: |
|---|
| 85 | | return post_sql |
|---|
| 86 | | |
|---|
| | 88 | |
|---|