Django

Code

Changeset 5336

Show
Ignore:
Timestamp:
05/24/07 20:29:10 (1 year ago)
Author:
jbronn
Message:

gis: (1) fixed WKT admin bug

(2) cleaned up GeometryField? (moved SQL creation into field, index creation now on by default)
(3) now have exact lookup type, e.g., filter(geom='...') works

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • django/branches/gis/django/contrib/gis/db/models/fields/__init__.py

    r5008 r5336  
    11# The Django base Field class. 
    22from django.db.models.fields import Field 
    3 from django.contrib.gis.db.models.postgis import POSTGIS_TERMS 
     3from django.contrib.gis.db.models.postgis import POSTGIS_TERMS, quotename 
    44from django.contrib.gis.oldforms import WKTField 
    55from django.utils.functional import curry 
    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 
     6from django.contrib.gis.geos import GEOSGeometry, GEOSException 
    377 
    388class GeometryField(Field): 
    39     "The base GIS field -- maps to the OpenGIS Geometry type." 
     9    "The base GIS field -- maps to the OpenGIS Specification Geometry type." 
    4010 
    4111    # The OpenGIS Geometry name. 
    4212    _geom = 'GEOMETRY' 
    4313 
    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        """ 
    5027        self._index = index 
     28        self._srid = srid 
     29        self._dim = dim 
     30        super(GeometryField, self).__init__(**kwargs) # Calling the parent initializtion function 
    5131 
    52         # The SRID for the geometry, defaults to 4326. 
    53         self._srid = srid 
     32    def _add_geom(self, style, db_table, field): 
     33        """Constructs the addition of the geometry to the table using the 
     34        AddGeometryColumn(...) PostGIS (and OGC standard) function. 
    5435 
    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 
    5748 
     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 
    5876 
    5977    def contribute_to_class(self, cls, name): 
     
    6583        setattr(cls, 'get_%s_centroid' % self.name, curry(cls._get_GEOM_centroid, field=self)) 
    6684        setattr(cls, 'get_%s_area' % self.name, curry(cls._get_GEOM_area, field=self)) 
    67  
     85         
    6886    def get_internal_type(self): 
    6987        return "NoField" 
    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                                                                 
    8789    def get_db_prep_lookup(self, lookup_type, value): 
    8890        """Returns field's value prepared for database lookup; the SRID of the geometry is 
  • django/branches/gis/django/contrib/gis/db/models/postgis.py

    r4884 r5336  
    2828    # A and B are the same feature, vertex-by-vertex, the operator returns true. 
    2929    'same_as' : '~= %s', 
     30    'exact' : '~= %s', 
    3031    # The "@" operator returns true if A's bounding box is completely contained by B's bounding box. 
    3132    'contained' : '@ %s', 
     
    5051    'relate' : 'Relate', 
    5152    } 
     53 
     54# The quotation used for postgis (uses single quotes). 
     55def quotename(value, dbl=False): 
     56    if dbl: return '"%s"' % value 
     57    else: return "'%s'" % value 
    5258 
    5359# These are the PostGIS-customized QUERY_TERMS, combines both the operators 
  • django/branches/gis/django/contrib/gis/oldforms/__init__.py

    r4883 r5336  
    77    def render(self, data): 
    88        # PostGIS uses EWKBHEX to store its values internally, converting 
    9         # to WKT for the admin first. 
    10         return super(WKTField, self).render(hex_to_wkt(data)) 
     9        # to WKT for the admin first -- unless there's no data, then just 
     10        # pass None to LargeTextField's render. 
     11        if not data: 
     12            return super(WKTField, self).render(None) 
     13        else: 
     14            return super(WKTField, self).render(hex_to_wkt(data)) 
    1115     
    1216