Author: jbronn
Date: 2007-10-08 13:18:17 -0500 (Mon, 08 Oct 2007)
New Revision: 6467

Added:
   django/branches/gis/django/contrib/gis/db/backend/postgis/models.py
   django/branches/gis/django/contrib/gis/db/backend/postgis/proxy.py
Removed:
   django/branches/gis/django/contrib/gis/db/models/proxy.py
Modified:
   django/branches/gis/django/contrib/gis/db/backend/__init__.py
   django/branches/gis/django/contrib/gis/db/backend/postgis/__init__.py
   django/branches/gis/django/contrib/gis/db/backend/postgis/field.py
   django/branches/gis/django/contrib/gis/db/models/fields/__init__.py
   django/branches/gis/django/contrib/gis/db/models/mixin.py
   django/branches/gis/django/contrib/gis/models.py
   django/branches/gis/django/contrib/gis/tests/geoapp/models.py
   django/branches/gis/django/contrib/gis/tests/geoapp/tests.py
   django/branches/gis/django/core/management/sql.py
Log:
gis: spatial-database compatibility and usability changes:
 (1) The SpatialRefSys and GeometryColumns models and GeometryProxy have been 
moved to the PostGIS backend because their functionality depends on the spatial 
databse.
 (2) The GeoMixin is no longer required, as all the functionality contributed 
by the extra instance methods has been moved to the GeometryProxy.
 (3) The `_post_create_sql` field now returns a tuple of SQL statements, 
instead of a string.


Modified: django/branches/gis/django/contrib/gis/db/backend/__init__.py
===================================================================
--- django/branches/gis/django/contrib/gis/db/backend/__init__.py       
2007-10-08 16:10:39 UTC (rev 6466)
+++ django/branches/gis/django/contrib/gis/db/backend/__init__.py       
2007-10-08 18:18:17 UTC (rev 6467)
@@ -1,15 +1,21 @@
 """
-  This module provides the backend for spatial SQL construction with Django.
+ This module provides the backend for spatial SQL construction with Django.
 
-  Specifically, this module will import the correct routines and modules
-    needed for GeoDjango
+ Specifically, this module will import the correct routines and modules
+ needed for GeoDjango.
+ 
+ (1) GeoBackEndField, a base class needed for GeometryField.
+ (2) GeometryProxy, for lazy-instantiated geometries from the 
+     database output.
+ (3) GIS_TERMS, a list of acceptable geographic lookup types for 
+     the backend.
+ (4) The `parse_lookup` function, used for spatial SQL construction by
+     the GeoQuerySet.
+ (5) The `create_spatial_db`, `geo_quotename`, and `get_geo_where_clause`
+     routines (needed by `parse_lookup`.
 
-   (1) GeoBackEndField, a base class needed for GeometryField.
-   (2) The parse_lookup() function, used for spatial SQL construction by
-       the GeoQuerySet.
-      
-  Currently only PostGIS is supported, but someday backends will be added for
-   additional spatial databases (e.g., Oracle, DB2).
+ Currently only PostGIS is supported, but someday backends will be added for
+ additional spatial databases (e.g., Oracle, DB2).
 """
 from django.conf import settings
 from django.db import connection
@@ -21,9 +27,11 @@
 ASGML, ASKML, UNION = (False, False, False)
 
 if settings.DATABASE_ENGINE == 'postgresql_psycopg2':
-    # PostGIS is the spatial database, getting the rquired modules, renaming 
as necessary.
+    # PostGIS is the spatial database, getting the rquired modules, 
+    # renaming as necessary.
     from django.contrib.gis.db.backend.postgis import \
         PostGISField as GeoBackendField, POSTGIS_TERMS as GIS_TERMS, \
+        PostGISProxy as GeometryProxy, \
         create_spatial_db, geo_quotename, get_geo_where_clause, \
         ASGML, ASKML, UNION
 else:

Modified: django/branches/gis/django/contrib/gis/db/backend/postgis/__init__.py
===================================================================
--- django/branches/gis/django/contrib/gis/db/backend/postgis/__init__.py       
2007-10-08 16:10:39 UTC (rev 6466)
+++ django/branches/gis/django/contrib/gis/db/backend/postgis/__init__.py       
2007-10-08 18:18:17 UTC (rev 6467)
@@ -7,6 +7,7 @@
     MAJOR_VERSION, MINOR_VERSION1, MINOR_VERSION2
 from django.contrib.gis.db.backend.postgis.creation import create_spatial_db
 from django.contrib.gis.db.backend.postgis.field import PostGISField
+from django.contrib.gis.db.backend.postgis.proxy import PostGISProxy
 
 # Functions used by GeoManager methods, and not via lookup types.
 if MAJOR_VERSION == 1:

Modified: django/branches/gis/django/contrib/gis/db/backend/postgis/field.py
===================================================================
--- django/branches/gis/django/contrib/gis/db/backend/postgis/field.py  
2007-10-08 16:10:39 UTC (rev 6466)
+++ django/branches/gis/django/contrib/gis/db/backend/postgis/field.py  
2007-10-08 18:18:17 UTC (rev 6467)
@@ -44,9 +44,11 @@
         return sql
 
     def _post_create_sql(self, style, db_table):
-        """Returns SQL that will be executed after the model has been
+        """
+        Returns SQL that will be executed after the model has been
         created. Geometry columns must be added after creation with the
-        PostGIS AddGeometryColumn() function."""
+        PostGIS AddGeometryColumn() function.
+        """
 
         # Getting the AddGeometryColumn() SQL necessary to create a PostGIS
         # geometry field.
@@ -54,9 +56,9 @@
 
         # If the user wants to index this data, then get the indexing SQL as 
well.
         if self._index:
-            return '%s\n%s' % (post_sql, self._geom_index(style, db_table))
+            return (post_sql, self._geom_index(style, db_table))
         else:
-            return post_sql
+            return (post_sql,)
 
     def _post_delete_sql(self, style, db_table):
         "Drops the geometry column."
@@ -66,9 +68,18 @@
             style.SQL_FIELD(quotename(self.column)) +  ');'
         return sql
 
+    def db_type(self):
+        """
+        PostGIS geometry columns are added by stored procedures, should be
+        None.
+        """
+        return None
+
     def get_db_prep_lookup(self, lookup_type, value):
-        """Returns field's value prepared for database lookup, accepts WKT and 
-        GEOS Geometries for the value."""
+        """
+        Returns field's value prepared for database lookup, accepts WKT and 
+        GEOS Geometries for the value.
+        """
         if lookup_type in POSTGIS_TERMS:
             if lookup_type == 'isnull': return [value] # special case for NULL 
geometries.
             if not bool(value): return [None] # If invalid value passed in.
@@ -101,6 +112,12 @@
         else:
             raise TypeError('Geometry Proxy should only return GEOSGeometry 
objects.')
 
+    def get_internal_type(self):
+        """
+        Returns NoField because a stored procedure is used by PostGIS to 
create the
+        """
+        return 'NoField'
+
     def get_placeholder(self, value):
         """
         Provides a proper substitution value for Geometries that are not in the

Added: django/branches/gis/django/contrib/gis/db/backend/postgis/models.py
===================================================================
--- django/branches/gis/django/contrib/gis/db/backend/postgis/models.py         
                (rev 0)
+++ django/branches/gis/django/contrib/gis/db/backend/postgis/models.py 
2007-10-08 18:18:17 UTC (rev 6467)
@@ -0,0 +1,54 @@
+"""
+ The GeometryColumns and SpatialRefSys models for the PostGIS backend.
+"""
+from django.db import models
+from django.contrib.gis.models import SpatialRefSysMixin
+
+# Checking for the presence of GDAL (needed for the SpatialReference object)
+from django.contrib.gis.gdal import HAS_GDAL
+if HAS_GDAL:
+    from django.contrib.gis.gdal import SpatialReference
+
+class GeometryColumns(models.Model):
+    """
+    The 'geometry_columns' table from the PostGIS. See the PostGIS
+    documentation at Ch. 4.2.2.
+    """
+    f_table_catalog = models.CharField(maxlength=256)
+    f_table_schema = models.CharField(maxlength=256)
+    f_table_name = models.CharField(maxlength=256, primary_key=True)
+    f_geometry_column = models.CharField(maxlength=256)
+    coord_dimension = models.IntegerField()
+    srid = models.IntegerField()
+    type = models.CharField(maxlength=30)
+
+    class Meta:
+        db_table = 'geometry_columns'
+
+    @classmethod
+    def table_name(self):
+        "Class method for returning the table name field for this model."
+        return 'f_table_name'
+
+    def __unicode__(self):
+        return "%s.%s - %dD %s field (SRID: %d)" % \
+               (self.f_table_name, self.f_geometry_column,
+                self.coord_dimension, self.type, self.srid)
+
+class SpatialRefSys(models.Model, SpatialRefSysMixin):
+    """
+    The 'spatial_ref_sys' table from PostGIS. See the PostGIS
+    documentaiton at Ch. 4.2.1.
+    """
+    srid = models.IntegerField(primary_key=True)
+    auth_name = models.CharField(maxlength=256)
+    auth_srid = models.IntegerField()
+    srtext = models.CharField(maxlength=2048)
+    proj4text = models.CharField(maxlength=2048)
+
+    class Meta:
+        db_table = 'spatial_ref_sys'
+
+    @property
+    def wkt(self):
+        return self.srtext

Copied: django/branches/gis/django/contrib/gis/db/backend/postgis/proxy.py 
(from rev 6466, django/branches/gis/django/contrib/gis/db/models/proxy.py)
===================================================================
--- django/branches/gis/django/contrib/gis/db/backend/postgis/proxy.py          
                (rev 0)
+++ django/branches/gis/django/contrib/gis/db/backend/postgis/proxy.py  
2007-10-08 18:18:17 UTC (rev 6467)
@@ -0,0 +1,62 @@
+"""
+ The GeometryProxy object, allows for lazy-geometries.  The proxy uses
+  Python descriptors for instantiating and setting GEOS Geometry objects
+  corresponding to geographic model fields.
+
+ Thanks to Robert Coup for providing this functionality (see #4322).
+"""
+
+from types import NoneType, StringType, UnicodeType
+
+class PostGISProxy(object): 
+    def __init__(self, klass, field): 
+        """
+        Proxy initializes on the given Geometry class (not an instance) and 
+        the GeometryField.
+        """
+        self._field = field 
+        self._klass = klass
+     
+    def __get__(self, obj, type=None): 
+        """
+        This accessor retrieves the geometry, initializing it using the 
geometry
+        class specified during initialization and the HEXEWKB value of the 
field.  
+        Currently, only GEOS or OGR geometries are supported.
+        """
+        # Getting the value of the field.
+        geom_value = obj.__dict__[self._field.attname] 
+        
+        if isinstance(geom_value, self._klass): 
+            geom = geom_value
+        elif (geom_value is None) or (geom_value==''):
+            geom = None
+        else: 
+            # Otherwise, a GEOSGeometry object is built using the field's 
contents,
+            #  and the model's corresponding attribute is set.
+            geom = self._klass(geom_value)
+            setattr(obj, self._field.attname, geom) 
+        return geom 
+     
+    def __set__(self, obj, value):
+        """
+        This accessor sets the proxied geometry with the geometry class
+        specified during initialization.  Values of None, HEXEWKB, or WKT may
+        be used to set the geometry as well.
+        """
+        # The OGC Geometry type of the field.
+        gtype = self._field._geom
+        
+        # The geometry type must match that of the field -- unless the
+        # general GeometryField is used.
+        if isinstance(value, self._klass) and (str(value.geom_type).upper() == 
gtype or gtype == 'GEOMETRY'):
+            # Assigning the SRID to the geometry.
+            if value.srid is None: value.srid = self._field._srid
+        elif isinstance(value, (NoneType, StringType, UnicodeType)):
+            # Set with None, WKT, or HEX
+            pass
+        else:
+            raise TypeError('cannot set %s GeometryProxy with value of type: 
%s' % (obj.__class__.__name__, type(value)))
+
+        # Setting the objects dictionary with the value, and returning.
+        obj.__dict__[self._field.attname] = value 
+        return value 

Modified: django/branches/gis/django/contrib/gis/db/models/fields/__init__.py
===================================================================
--- django/branches/gis/django/contrib/gis/db/models/fields/__init__.py 
2007-10-08 16:10:39 UTC (rev 6466)
+++ django/branches/gis/django/contrib/gis/db/models/fields/__init__.py 
2007-10-08 18:18:17 UTC (rev 6467)
@@ -1,9 +1,9 @@
-from django.contrib.gis.db.backend import GeoBackendField # depends on the 
spatial database backend.
-from django.contrib.gis.db.models.proxy import GeometryProxy
+from django.conf import settings
+from django.contrib.gis.db.backend import GeoBackendField, GeometryProxy # 
these depend on the spatial database backend.
 from django.contrib.gis.oldforms import WKTField
-from django.utils.functional import curry
+from django.contrib.gis.geos import GEOSGeometry
 
-#TODO: Flesh out widgets.
+#TODO: Flesh out widgets; consider adding support for OGR Geometry proxies.
 class GeometryField(GeoBackendField):
     "The base GIS field -- maps to the OpenGIS Specification Geometry type."
 
@@ -31,26 +31,9 @@
     def contribute_to_class(self, cls, name):
         super(GeometryField, self).contribute_to_class(cls, name)
 
-        # setup for lazy-instantiated GEOSGeometry objects
-        setattr(cls, self.attname, GeometryProxy(self))
-
-        # Adding needed accessor functions
-        setattr(cls, 'get_%s_geos' % self.name, curry(cls._get_GEOM_geos, 
field=self))
-        setattr(cls, 'get_%s_ogr' % self.name, curry(cls._get_GEOM_ogr, 
field=self, srid=self._srid))
-        setattr(cls, 'get_%s_srid' % self.name, curry(cls._get_GEOM_srid, 
srid=self._srid))
-        setattr(cls, 'get_%s_srs' % self.name, curry(cls._get_GEOM_srs, 
srid=self._srid))
-        setattr(cls, 'get_%s_wkt' % self.name, curry(cls._get_GEOM_wkt, 
field=self))
-        setattr(cls, 'get_%s_centroid' % self.name, 
curry(cls._get_GEOM_centroid, field=self))
-        setattr(cls, 'get_%s_area' % self.name, curry(cls._get_GEOM_area, 
field=self))
+        # Setup for lazy-instantiated GEOSGeometry object.
+        setattr(cls, self.attname, GeometryProxy(GEOSGeometry, self))
         
-    def get_internal_type(self):
-        return "NoField"
-
-    def db_type(self):
-        # Geometry columns are added by stored procedures, and thus should
-        #  be None.
-        return None
-                                                                
     def get_manipulator_field_objs(self):
         "Using the WKTField (defined above) to be our manipulator."
         return [WKTField]

Modified: django/branches/gis/django/contrib/gis/db/models/mixin.py
===================================================================
--- django/branches/gis/django/contrib/gis/db/models/mixin.py   2007-10-08 
16:10:39 UTC (rev 6466)
+++ django/branches/gis/django/contrib/gis/db/models/mixin.py   2007-10-08 
18:18:17 UTC (rev 6467)
@@ -1,54 +1,11 @@
-from warnings import warn
-
-# GEOS is a requirement, GDAL is not
-from django.contrib.gis.geos import GEOSGeometry
-from django.contrib.gis.gdal import HAS_GDAL
-if HAS_GDAL:
-    from django.contrib.gis.gdal import OGRGeometry, SpatialReference
-
 # Until model subclassing is a possibility, a mixin class is used to add
 # the necessary functions that may be contributed for geographic objects.
 class GeoMixin:
-    "The Geographic Mixin class provides routines for geographic objects."
-
-    # A subclass of Model is specifically needed so that these geographic
-    # routines are present for instantiations of the models.
-    def _get_GEOM_geos(self, field):
-        "Returns a GEOS Python object for the geometry."
-        warn("use model.%s" % field.attname, DeprecationWarning) 
-        return getattr(self, field.attname)
-
-    def _get_GEOM_ogr(self, field, srid):
-        "Returns an OGR Python object for the geometry."
-        if HAS_GDAL:
-            return OGRGeometry(getattr(self, field.attname).wkt,
-                               SpatialReference('EPSG:%d' % srid))
-        else:
-            raise Exception, "GDAL is not installed!"
-
-    def _get_GEOM_srid(self, srid):
-        "Returns the spatial reference identifier (SRID) of the geometry."
-        warn("use model.geometry_field.srid", DeprecationWarning)
-        return srid
-
-    def _get_GEOM_srs(self, srid):
-        "Returns ane OGR Spatial Reference object of the geometry."
-        if HAS_GDAL:
-            return SpatialReference('EPSG:%d' % srid)
-        else:
-            raise Exception, "GDAL is not installed!"
-
-    def _get_GEOM_wkt(self, field):
-        "Returns the WKT of the geometry."
-        warn("use model.%s.centroid.wkt" % field.attname, DeprecationWarning) 
-        return getattr(self, field.attname).wkt
-
-    def _get_GEOM_centroid(self, field):
-        "Returns the centroid of the geometry, in WKT."
-        warn("use model.%s.centroid.wkt" % field.attname, DeprecationWarning) 
-        return getattr(self, field.attname).centroid.wkt
-    
-    def _get_GEOM_area(self, field):
-        "Returns the area of the geometry, in projected units."
-        warn("use model.%s.area" % field.attname, DeprecationWarning)
-        return getattr(self, field.attname).area
+    """
+    The Geographic Mixin class provides routines for geographic objects,
+    however, it is no longer necessary, since all of its previous functions 
+    may now be accessed via the GeometryProxy.  This mixin is only provided
+    for backwards-compatibility purposes, and will be eventually removed
+    (unless the need arises again).
+    """
+    pass

Deleted: django/branches/gis/django/contrib/gis/db/models/proxy.py
===================================================================
--- django/branches/gis/django/contrib/gis/db/models/proxy.py   2007-10-08 
16:10:39 UTC (rev 6466)
+++ django/branches/gis/django/contrib/gis/db/models/proxy.py   2007-10-08 
18:18:17 UTC (rev 6467)
@@ -1,47 +0,0 @@
-"""
-  The GeometryProxy object, allows for lazy-geometries.  The proxy uses
-   Python descriptors for instantiating and setting GEOS Geometry objects
-   corresponding to geographic model fields.
-
-  Thanks to Robert Coup for providing this functionality (see #4322).
-"""
-
-from types import NoneType, StringType, UnicodeType
-from django.contrib.gis.geos import GEOSGeometry, GEOSException 
-
-# TODO: docstrings
-class GeometryProxy(object): 
-    def __init__(self, field): 
-        "Proxy initializes on the given GeometryField."
-        self._field = field 
-     
-    def __get__(self, obj, type=None): 
-        # Getting the value of the field.
-        geom_value = obj.__dict__[self._field.attname] 
-
-        if isinstance(geom_value, GEOSGeometry): 
-            # If the value of the field is None, or is already a GEOS Geometry
-            #  no more work is needed.
-            geom = geom_value
-        elif (geom_value is None) or (geom_value==''):
-            geom = None
-        else: 
-            # Otherwise, a GEOSGeometry object is built using the field's 
contents,
-            #  and the model's corresponding attribute is set.
-            geom = GEOSGeometry(geom_value)
-            setattr(obj, self._field.attname, geom) 
-        return geom 
-     
-    def __set__(self, obj, value): 
-        if isinstance(value, GEOSGeometry) and (value.geom_type.upper() == 
self._field._geom):
-            # Getting set with GEOS Geometry; geom_type must match that of the 
field.
-
-            # If value's SRID is not set, setting it to the field's SRID.
-            if value.srid is None: value.srid = self._field._srid
-        elif isinstance(value, (NoneType, StringType, UnicodeType)):
-            # Getting set with None, WKT, or HEX
-            pass
-        else:
-            raise TypeError, 'cannot set %s GeometryProxy with value of type: 
%s' % (self._field._geom, type(value))
-        obj.__dict__[self._field.attname] = value 
-        return value 

Modified: django/branches/gis/django/contrib/gis/models.py
===================================================================
--- django/branches/gis/django/contrib/gis/models.py    2007-10-08 16:10:39 UTC 
(rev 6466)
+++ django/branches/gis/django/contrib/gis/models.py    2007-10-08 18:18:17 UTC 
(rev 6467)
@@ -1,8 +1,9 @@
 """
- Models for the PostGIS/OGC database tables.
+ Imports the SpatialRefSys and GeometryColumns models dependent on the
+ spatial database backend.
 """
 import re
-from django.db import models
+from django.conf import settings
 
 # Checking for the presence of GDAL (needed for the SpatialReference object)
 from django.contrib.gis.gdal import HAS_GDAL
@@ -15,37 +16,11 @@
 #        parameter.
 spheroid_regex = 
re.compile(r'.+SPHEROID\[\"(?P<name>.+)\",(?P<major>\d+(\.\d+)?),(?P<flattening>\d{3}\.\d+),')
 
-# This is the global 'geometry_columns' from PostGIS.
-#   See PostGIS Documentation at Ch. 4.2.2
-class GeometryColumns(models.Model):
-    f_table_catalog = models.CharField(maxlength=256)
-    f_table_schema = models.CharField(maxlength=256)
-    f_table_name = models.CharField(maxlength=256, primary_key=True)
-    f_geometry_column = models.CharField(maxlength=256)
-    coord_dimension = models.IntegerField()
-    srid = models.IntegerField()
-    type = models.CharField(maxlength=30)
-
-    class Meta:
-        db_table = 'geometry_columns'
-
-    def __str__(self):
-        return "%s.%s - %dD %s field (SRID: %d)" % \
-               (self.f_table_name, self.f_geometry_column,
-                self.coord_dimension, self.type, self.srid)
-
-# This is the global 'spatial_ref_sys' table from PostGIS.
-#   See PostGIS Documentation at Ch. 4.2.1
-class SpatialRefSys(models.Model):
-    srid = models.IntegerField(primary_key=True)
-    auth_name = models.CharField(maxlength=256)
-    auth_srid = models.IntegerField()
-    srtext = models.CharField(maxlength=2048)
-    proj4text = models.CharField(maxlength=2048)
-
-    class Meta:
-        db_table = 'spatial_ref_sys'
-
+class SpatialRefSysMixin(object):
+    """
+    The SpatialRefSysMixin is a class used by the database-dependent
+    SpatialRefSys objects to reduce redundnant code.
+    """
     @property
     def srs(self):
         """
@@ -58,24 +33,17 @@
             else:
                 # Attempting to cache a SpatialReference object.
 
-                # Trying to get from WKT first
+                # Trying to get from WKT first.
                 try:
-                    self._srs = SpatialReference(self.srtext, 'wkt')
-                    return self._srs.clone()
-                except Exception, msg1:
+                    self._srs = SpatialReference(self.wkt)
+                    return self.srs
+                except Exception, msg:
                     pass
-
-                # Trying the proj4 text next
-                try:
-                    self._srs = SpatialReference(self.proj4text, 'proj4')
-                    return self._srs.clone()
-                except Exception, msg2:
-                    pass
-
-                raise Exception, 'Could not get an OSR Spatial 
Reference:\n\tWKT error: %s\n\tPROJ.4 error: %s' % (msg1, msg2)
+                
+                raise Exception('Could not get OSR SpatialReference from WKT: 
%s\nError:\n%s' % (self.wkt, msg))
         else:
-            raise Exception, 'GDAL is not installed!'
-                                                                               
 
+            raise Exception('GDAL is not installed.')
+
     @property
     def ellipsoid(self):
         """
@@ -85,7 +53,7 @@
         if HAS_GDAL:
             return self.srs.ellipsoid
         else:
-            m = spheroid_regex.match(self.srtext)
+            m = spheroid_regex.match(self.wkt)
             if m: return (float(m.group('major')), 
float(m.group('flattening')))
             else: return None
 
@@ -139,10 +107,18 @@
         "Returns the name of the angular units."
         return self.srs.angular_name
 
-    def __str__(self):
+    def __unicode__(self):
         """
         Returns the string representation.  If GDAL is installed,
         it will be 'pretty' OGC WKT.
         """
-        if HAS_GDAL: return str(self.srs)
-        else: return "%d:%s " % (self.srid, self.auth_name)
+        try:
+            return unicode(self.srs)
+        except:
+            return unicode(self.srtext)
+
+# The SpatialRefSys and GeometryColumns models
+if settings.DATABASE_ENGINE == 'postgresql_psycopg2':
+    from django.contrib.gis.db.backend.postgis.models import GeometryColumns, 
SpatialRefSys
+else:
+    raise NotImplementedError('No SpatialRefSys or GeometryColumns models for 
backend: %s' % settings.DATABASE_ENGINE)

Modified: django/branches/gis/django/contrib/gis/tests/geoapp/models.py
===================================================================
--- django/branches/gis/django/contrib/gis/tests/geoapp/models.py       
2007-10-08 16:10:39 UTC (rev 6466)
+++ django/branches/gis/django/contrib/gis/tests/geoapp/models.py       
2007-10-08 18:18:17 UTC (rev 6467)
@@ -1,16 +1,21 @@
 from django.contrib.gis.db import models
 
-class Country(models.Model, models.GeoMixin):
-    name = models.CharField(maxlength=30)
+class Country(models.Model):
+    name = models.CharField(max_length=30)
     mpoly = models.MultiPolygonField() # SRID, by default, is 4326
     objects = models.GeoManager()
 
-class City(models.Model, models.GeoMixin):
-    name = models.CharField(maxlength=30)
+class City(models.Model):
+    name = models.CharField(max_length=30)
     point = models.PointField() 
     objects = models.GeoManager()
 
-class State(models.Model, models.GeoMixin):
-    name = models.CharField(maxlength=30)
+class State(models.Model):
+    name = models.CharField(max_length=30)
     poly = models.PolygonField(null=True) # Allowing NULL geometries here.
     objects = models.GeoManager()
+
+class Feature(models.Model):
+    name = models.CharField(max_length=20)
+    geom = models.GeometryField()
+    objects = models.GeoManager()

Modified: django/branches/gis/django/contrib/gis/tests/geoapp/tests.py
===================================================================
--- django/branches/gis/django/contrib/gis/tests/geoapp/tests.py        
2007-10-08 16:10:39 UTC (rev 6466)
+++ django/branches/gis/django/contrib/gis/tests/geoapp/tests.py        
2007-10-08 18:18:17 UTC (rev 6467)
@@ -1,6 +1,7 @@
 import unittest
-from models import Country, City, State
-from django.contrib.gis.geos import fromstr, Point, LineString, LinearRing, 
Polygon
+from models import Country, City, State, Feature
+from django.contrib.gis.geos import *
+from django.contrib.gis import gdal
 
 class GeoModelTest(unittest.TestCase):
     
@@ -59,8 +60,17 @@
         nullstate = State(name='NullState', poly=ply)
         self.assertEqual(4326, nullstate.poly.srid) # SRID auto-set from None
         nullstate.save()
-        self.assertEqual(ply, State.objects.get(name='NullState').poly)
+
+        ns = State.objects.get(name='NullState')
+        self.assertEqual(ply, ns.poly)
         
+        # Testing the `ogr` and `srs` lazy-geometry properties.
+        if gdal.HAS_GDAL:
+            self.assertEqual(True, isinstance(ns.poly.ogr, gdal.OGRGeometry))
+            self.assertEqual(ns.poly.wkb, ns.poly.ogr.wkb)
+            self.assertEqual(True, isinstance(ns.poly.srs, 
gdal.SpatialReference))
+            self.assertEqual('WGS 84', ns.poly.srs.name)
+
         # Changing the interior ring on the poly attribute.
         new_inner = LinearRing((30, 30), (30, 70), (70, 70), (70, 30), (30, 
30))
         nullstate.poly[1] = new_inner.clone()
@@ -277,6 +287,32 @@
         self.assertEqual(True, union.equals_exact(u, 10)) # Going up to 10 
digits of precision.
         qs = City.objects.filter(name='NotACity')
         self.assertEqual(None, qs.union('point'))
+
+    def test18_geometryfield(self):
+        "Testing GeometryField."
+        f1 = Feature(name='Point', geom=Point(1, 1))
+        f2 = Feature(name='LineString', geom=LineString((0, 0), (1, 1), (5, 
5)))
+        f3 = Feature(name='Polygon', geom=Polygon(LinearRing((0, 0), (0, 5), 
(5, 5), (5, 0), (0, 0))))
+        f4 = Feature(name='GeometryCollection', 
+                     geom=GeometryCollection(Point(2, 2), LineString((0, 0), 
(2, 2)), 
+                                             Polygon(LinearRing((0, 0), (0, 
5), (5, 5), (5, 0), (0, 0)))))
+        f1.save()
+        f2.save()
+        f3.save()
+        f4.save()
+
+        f_1 = Feature.objects.get(name='Point')
+        self.assertEqual(True, isinstance(f_1.geom, Point))
+        self.assertEqual((1.0, 1.0), f_1.geom.tuple)
+        f_2 = Feature.objects.get(name='LineString')
+        self.assertEqual(True, isinstance(f_2.geom, LineString))
+        self.assertEqual(((0.0, 0.0), (1.0, 1.0), (5.0, 5.0)), f_2.geom.tuple)
+
+        f_3 = Feature.objects.get(name='Polygon')
+        self.assertEqual(True, isinstance(f_3.geom, Polygon))
+        f_4 = Feature.objects.get(name='GeometryCollection')
+        self.assertEqual(True, isinstance(f_4.geom, GeometryCollection))
+        self.assertEqual(f_3.geom, f_4.geom[2])
     
 def suite():
     s = unittest.TestSuite()

Modified: django/branches/gis/django/core/management/sql.py
===================================================================
--- django/branches/gis/django/core/management/sql.py   2007-10-08 16:10:39 UTC 
(rev 6466)
+++ django/branches/gis/django/core/management/sql.py   2007-10-08 18:18:17 UTC 
(rev 6467)
@@ -404,7 +404,7 @@
     # Post-creation SQL should come before any initial SQL data is loaded.
     for f in opts.fields:
         if hasattr(f, '_post_create_sql'):
-            output.append(f._post_create_sql(style, model._meta.db_table))
+            output.extend(f._post_create_sql(style, model._meta.db_table))
 
     # Some backends can't execute more than one SQL statement at a time,
     # so split into separate statements.


--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/django-updates?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to