Changeset 5806
- Timestamp:
- 08/05/07 20:27:22 (1 year ago)
- Files:
-
- django/branches/gis/django/contrib/gis/db/backend/postgis/__init__.py (modified) (1 diff)
- django/branches/gis/django/contrib/gis/db/models/manager.py (modified) (1 diff)
- django/branches/gis/django/contrib/gis/db/models/proxy.py (modified) (1 diff)
- django/branches/gis/django/contrib/gis/db/models/query.py (modified) (2 diffs)
- django/branches/gis/django/contrib/gis/tests/geoapp/tests.py (modified) (5 diffs)
- django/branches/gis/django/contrib/gis/utils/LayerMapping.py (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
django/branches/gis/django/contrib/gis/db/backend/postgis/__init__.py
r5776 r5806 2 2 The PostGIS spatial database backend module. 3 3 """ 4 from query import get_geo_where_clause, GEOM_FUNC_PREFIX, POSTGIS_TERMS 4 from query import \ 5 get_geo_where_clause, GEOM_FUNC_PREFIX, POSTGIS_TERMS, \ 6 MAJOR_VERSION, MINOR_VERSION1, MINOR_VERSION2 5 7 from creation import create_spatial_db 6 8 from field import PostGISField 7 9 10 # Whether PostGIS has AsKML() support. 11 if MAJOR_VERSION == 1: 12 # AsKML() only supported in versions 1.2.1+ 13 if MINOR_VERSION1 == 3: 14 ASKML = 'ST_AsKML' 15 elif MINOR_VERSION1 == 2 and MINOR_VERSION2 >= 1: 16 ASKML = 'AsKML' 17 django/branches/gis/django/contrib/gis/db/models/manager.py
r5751 r5806 8 8 return GeoQuerySet(model=self.model) 9 9 10 def kml(self, field_name ):11 return self.get_query_set().kml(field_name )10 def kml(self, field_name, **kwargs): 11 return self.get_query_set().kml(field_name, **kwargs) django/branches/gis/django/contrib/gis/db/models/proxy.py
r5762 r5806 1 1 """ 2 The GeometryProxy object, allows for lazy-geometries. 2 The GeometryProxy object, allows for lazy-geometries. The proxy uses 3 Python descriptors for instantiating and setting GEOS Geometry objects 4 corresponding to geographic model fields. 3 5 4 6 Thanks to Robert Coup for providing this functionality (see #4322). 5 7 """ 6 8 7 # GEOS Routines 9 from types import NoneType, StringType, UnicodeType 8 10 from django.contrib.gis.geos import GEOSGeometry, GEOSException 9 11 10 # TODO: docstrings & comments12 # TODO: docstrings 11 13 class GeometryProxy(object): 12 14 def __init__(self, field): 15 "Proxy initializes on the given GeometryField." 13 16 self._field = field 14 17 15 18 def __get__(self, obj, type=None): 19 # Getting the value of the field. 16 20 geom_value = obj.__dict__[self._field.attname] 21 17 22 if (geom_value is None) or (isinstance(geom_value, GEOSGeometry)): 23 # If the value of the field is None, or is already a GEOS Geometry 24 # no more work is needed. 18 25 geom = geom_value 19 26 else: 20 geom = GEOSGeometry(geom_value) 27 # Otherwise, a GEOSGeometry object is built using the field's contents, 28 # and the model's corresponding attribute is set. 29 geom = GEOSGeometry(geom_value) 21 30 setattr(obj, self._field.attname, geom) 22 31 return geom 23 32 24 33 def __set__(self, obj, value): 25 if isinstance(value, GEOSGeometry): 26 if value and ((value.srid is None) and (self._field._srid is not None)): 27 value.srid = self._field._srid 28 34 if isinstance(value, GEOSGeometry) and (value.geom_type.upper() == self._field._geom): 35 # Getting set with GEOS Geometry; geom_type must match that of the field. 36 37 # If value's SRID is not set, setting it to the field's SRID. 38 if value.srid is None: value.srid = self._field._srid 39 elif isinstance(value, (NoneType, StringType, UnicodeType)): 40 # Getting set with None, WKT, or HEX 41 pass 42 else: 43 raise TypeError, 'cannot set %s GeometryProxy with value of type: %s' % (self._field._geom, type(value)) 29 44 obj.__dict__[self._field.attname] = value 30 45 return value django/branches/gis/django/contrib/gis/db/models/query.py
r5776 r5806 1 import operator 2 from django.core.exceptions import ImproperlyConfigured 3 from django.db import backend 1 4 from django.db.models.query import Q, QuerySet 2 from django.db import backend5 from django.db.models.fields import FieldDoesNotExist 3 6 from django.contrib.gis.db.models.fields import GeometryField 4 7 from django.contrib.gis.db.backend import parse_lookup # parse_lookup depends on the spatial database backend. 5 from django.db.models.fields import FieldDoesNotExist6 import operator7 8 8 9 class GeoQ(Q): … … 38 39 return clone 39 40 40 def kml(self, field_name): 41 def kml(self, field_name, precision=8): 42 """Returns KML representation of the given field name in a `kml` 43 attribute on each element of the QuerySet.""" 44 # Is KML output supported? 45 try: 46 from django.contrib.gis.db.backend.postgis import ASKML 47 except ImportError: 48 raise ImproperlyConfigured, 'AsKML() only available in PostGIS versions 1.2.1 and greater.' 49 50 # Is the given field name a geographic field? 41 51 field = self.model._meta.get_field(field_name) 42 52 if not isinstance(field, GeometryField): 53 raise TypeError, 'KML output only available on GeometryField fields.' 43 54 field_col = "%s.%s" % (backend.quote_name(self.model._meta.db_table), 44 backend.quote_name(field.column))55 backend.quote_name(field.column)) 45 56 46 return self.extra(select={'kml':'AsKML(%s,6)' % field_col}) 57 # Adding the AsKML function call to the SELECT part of the SQL. 58 return self.extra(select={'kml':'%s(%s,%s)' % (ASKML, field_col, precision)}) django/branches/gis/django/contrib/gis/tests/geoapp/tests.py
r5776 r5806 1 1 import unittest 2 2 from models import Country, City, State 3 from django.contrib.gis.geos import fromstr 3 from django.contrib.gis.geos import fromstr, Point, LineString, LinearRing, Polygon 4 4 5 5 class GeoModelTest(unittest.TestCase): 6 6 7 def test0 01_initial_sql(self):7 def test01_initial_sql(self): 8 8 "Testing geographic initial SQL." 9 9 … … 13 13 self.assertEqual(3, State.objects.count()) 14 14 15 def test002_contains_contained(self): 15 def test02_proxy(self): 16 "Testing Lazy-Geometry support (using the GeometryProxy)." 17 #### Testing on a Point 18 pnt = Point(0, 0) 19 nullcity = City(name='NullCity', point=pnt) 20 nullcity.save() 21 22 # Making sure TypeError is thrown when trying to set with an 23 # incompatible type. 24 for bad in [5, 2.0, LineString((0, 0), (1, 1))]: 25 try: 26 nullcity.point = bad 27 except TypeError: 28 pass 29 else: 30 self.fail('Should throw a TypeError') 31 32 # Now setting with a compatible GEOS Geometry, saving, and ensuring 33 # the save took, notice no SRID is explicitly set. 34 new = Point(5, 23) 35 nullcity.point = new 36 37 # Ensuring that the SRID is automatically set to that of the 38 # field after assignment, but before saving. 39 self.assertEqual(4326, nullcity.point.srid) 40 nullcity.save() 41 42 # Ensuring the point was saved correctly after saving 43 self.assertEqual(new, City.objects.get(name='NullCity').point) 44 45 # Setting the X and Y of the Point 46 nullcity.point.x = 23 47 nullcity.point.y = 5 48 # Checking assignments pre & post-save. 49 self.assertNotEqual(Point(23, 5), City.objects.get(name='NullCity').point) 50 nullcity.save() 51 self.assertEqual(Point(23, 5), City.objects.get(name='NullCity').point) 52 nullcity.delete() 53 54 #### Testing on a Polygon 55 shell = LinearRing((0, 0), (0, 100), (100, 100), (100, 0), (0, 0)) 56 inner = LinearRing((40, 40), (40, 60), (60, 60), (60, 40), (40, 40)) 57 58 # Creating a State object using a built Polygon 59 ply = Polygon(shell.clone(), inner.clone()) 60 nullstate = State(name='NullState', poly=ply) 61 self.assertEqual(4326, nullstate.poly.srid) # SRID auto-set from None 62 nullstate.save() 63 self.assertEqual(ply, State.objects.get(name='NullState').poly) 64 65 # Changing the interior ring on the poly attribute. 66 new_inner = LinearRing((30, 30), (30, 70), (70, 70), (70, 30), (30, 30)) 67 nullstate.poly[1] = new_inner.clone() 68 ply[1] = new_inner 69 self.assertEqual(4326, nullstate.poly.srid) 70 nullstate.save() 71 self.assertEqual(ply, State.objects.get(name='NullState').poly) 72 nullstate.delete() 73 74 def test03_kml(self): 75 "Testing KML output from the database using GeoManager.kml()." 76 # Should throw an error trying to get KML from a non-geometry field. 77 try: 78 qs = City.objects.all().kml('name') 79 except TypeError: 80 pass 81 else: 82 self.fail('Expected a TypeError exception') 83 84 # Ensuring the KML is as expected. 85 ptown = City.objects.kml('point', precision=9).get(name='Pueblo') 86 self.assertEqual('<Point><coordinates>-104.609252,38.255001,0</coordinates></Point>', ptown.kml) 87 88 def test10_contains_contained(self): 16 89 "Testing the 'contained' and 'contains' lookup types." 17 90 … … 48 121 self.assertEqual(0, len(Country.objects.filter(mpoly__contains=okcity.point.wkt))) # Qeury w/WKT 49 122 50 def test 003_lookup_insert_transform(self):123 def test11_lookup_insert_transform(self): 51 124 "Testing automatic transform for lookups and inserts." 52 125 … … 70 143 self.assertAlmostEqual(wgs_pnt.y, sa.point.y, 6) 71 144 72 def test 004_null_geometries(self):145 def test12_null_geometries(self): 73 146 "Testing NULL geometry support." 74 147 … … 91 164 nmi.save() 92 165 93 def test 005_left_right(self):166 def test13_left_right(self): 94 167 "Testing the 'left' and 'right' lookup types." 95 168 django/branches/gis/django/contrib/gis/utils/LayerMapping.py
r5755 r5806 269 269 ct = CoordTransform(self.source_srs, target_srs) 270 270 except Exception, msg: 271 raise Exception, 'Could not translate between the data source and model geometry .'271 raise Exception, 'Could not translate between the data source and model geometry: %s' % msg 272 272 273 273 for feat in self.layer:
