Django

Code

root/django/branches/gis/django/contrib/gis/tests/geoapp/tests_mysql.py

Revision 7641, 7.7 kB (checked in by jbronn, 5 months ago)

gis: Refactor of the GeoQuerySet; new features include:

(1) Creation of internal API that eases generation of GeoQuerySet methods.
(2) GeoQuerySet.distance now returns Distance objects instead of floats.
(3) Added the new GeoQuerySet methods: area, centroid, difference, envelope, intersection, length, make_line, mem_size, num_geom, num_points, perimeter, point_on_surface, scale, svg, sym_difference, translate, union.
(4) The model_att keyword may be used to customize the attribute that GeoQuerySet methods attach output to.
(5) Geographic distance lookups and GeoQuerySet.distance calls now use ST_distance_sphere by default (performance benefits far outweigh small loss in accuracy); ST_distance_spheroid may still be used by specifying an option.
(6) GeoQuerySet methods may now operate accross ForeignKey? relations specified via the field_name keyword (but this does not work on Oracle).
(7) Area now has the same units of measure as Distance.

Backward Incompatibilites:

  • The aggregate union method is now known as unionagg.
  • The field_name keyword used for GeoQuerySet methods may no longer be specified via positional arguments.
  • Distance objects returned instead of floats from GeoQuerySet.distance.
  • ST_Distance_sphere used by default for geographic distance calculations.
Line 
1 """
2  A limited test module is used for a limited spatial database.
3 """
4 import os, unittest
5 from models import Country, City, State, Feature
6 from django.contrib.gis import gdal
7 from django.contrib.gis.geos import *
8 from django.core.exceptions import ImproperlyConfigured
9
10 class GeoModelTest(unittest.TestCase):
11    
12     def test01_initial_sql(self):
13         "Testing geographic initial SQL."
14         # Ensuring that data was loaded from initial SQL.
15         self.assertEqual(2, Country.objects.count())
16         self.assertEqual(8, City.objects.count())
17         self.assertEqual(2, State.objects.count())
18
19     def test02_proxy(self):
20         "Testing Lazy-Geometry support (using the GeometryProxy)."
21         #### Testing on a Point
22         pnt = Point(0, 0)
23         nullcity = City(name='NullCity', point=pnt)
24         nullcity.save()
25
26         # Making sure TypeError is thrown when trying to set with an
27         #  incompatible type.
28         for bad in [5, 2.0, LineString((0, 0), (1, 1))]:
29             try:
30                 nullcity.point = bad
31             except TypeError:
32                 pass
33             else:
34                 self.fail('Should throw a TypeError')
35
36         # Now setting with a compatible GEOS Geometry, saving, and ensuring
37         #  the save took, notice no SRID is explicitly set.
38         new = Point(5, 23)
39         nullcity.point = new
40
41         # Ensuring that the SRID is automatically set to that of the
42         #  field after assignment, but before saving.
43         self.assertEqual(4326, nullcity.point.srid)
44         nullcity.save()
45
46         # Ensuring the point was saved correctly after saving
47         self.assertEqual(new, City.objects.get(name='NullCity').point)
48
49         # Setting the X and Y of the Point
50         nullcity.point.x = 23
51         nullcity.point.y = 5
52         # Checking assignments pre & post-save.
53         self.assertNotEqual(Point(23, 5), City.objects.get(name='NullCity').point)
54         nullcity.save()
55         self.assertEqual(Point(23, 5), City.objects.get(name='NullCity').point)
56         nullcity.delete()
57
58         #### Testing on a Polygon
59         shell = LinearRing((0, 0), (0, 100), (100, 100), (100, 0), (0, 0))
60         inner = LinearRing((40, 40), (40, 60), (60, 60), (60, 40), (40, 40))
61
62         # Creating a State object using a built Polygon
63         ply = Polygon(shell, inner)
64         nullstate = State(name='NullState', poly=ply)
65         self.assertEqual(4326, nullstate.poly.srid) # SRID auto-set from None
66         nullstate.save()
67
68         ns = State.objects.get(name='NullState')
69         self.assertEqual(ply, ns.poly)
70        
71         # Testing the `ogr` and `srs` lazy-geometry properties.
72         if gdal.HAS_GDAL:
73             self.assertEqual(True, isinstance(ns.poly.ogr, gdal.OGRGeometry))
74             self.assertEqual(ns.poly.wkb, ns.poly.ogr.wkb)
75             self.assertEqual(True, isinstance(ns.poly.srs, gdal.SpatialReference))
76             self.assertEqual('WGS 84', ns.poly.srs.name)
77
78         # Changing the interior ring on the poly attribute.
79         new_inner = LinearRing((30, 30), (30, 70), (70, 70), (70, 30), (30, 30))
80         ns.poly[1] = new_inner
81         ply[1] = new_inner
82         self.assertEqual(4326, ns.poly.srid)
83         ns.save()
84         self.assertEqual(ply, State.objects.get(name='NullState').poly)
85         ns.delete()
86
87     def test03_contains_contained(self):
88         "Testing the 'contained', 'contains', and 'bbcontains' lookup types."
89         # Getting Texas, yes we were a country -- once ;)
90         texas = Country.objects.get(name='Texas')
91        
92         # Seeing what cities are in Texas, should get Houston and Dallas,
93         #  and Oklahoma City because MySQL 'within' only checks on the
94         #  _bounding box_ of the Geometries.
95         qs = City.objects.filter(point__within=texas.mpoly)
96         self.assertEqual(3, qs.count())
97         cities = ['Houston', 'Dallas', 'Oklahoma City']
98         for c in qs: self.assertEqual(True, c.name in cities)
99
100         # Pulling out some cities.
101         houston = City.objects.get(name='Houston')
102         wellington = City.objects.get(name='Wellington')
103         pueblo = City.objects.get(name='Pueblo')
104         okcity = City.objects.get(name='Oklahoma City')
105         lawrence = City.objects.get(name='Lawrence')
106
107         # Now testing contains on the countries using the points for
108         #  Houston and Wellington.
109         tx = Country.objects.get(mpoly__contains=houston.point) # Query w/GEOSGeometry
110         nz = Country.objects.get(mpoly__contains=wellington.point.hex) # Query w/EWKBHEX
111         ks = State.objects.get(poly__contains=lawrence.point)
112         self.assertEqual('Texas', tx.name)
113         self.assertEqual('New Zealand', nz.name)
114         self.assertEqual('Kansas', ks.name)
115
116         # Pueblo is not contained in Texas or New Zealand.
117         self.assertEqual(0, len(Country.objects.filter(mpoly__contains=pueblo.point))) # Query w/GEOSGeometry object
118
119         # OK City is contained w/in bounding box of Texas.
120         qs = Country.objects.filter(mpoly__bbcontains=okcity.point)
121         self.assertEqual(1, len(qs))
122         self.assertEqual('Texas', qs[0].name)
123
124     def test04_disjoint(self):
125         "Testing the `disjoint` lookup type."
126         ptown = City.objects.get(name='Pueblo')
127         qs1 = City.objects.filter(point__disjoint=ptown.point)
128         self.assertEqual(7, qs1.count())
129         # TODO: This query should work in MySQL, but it appears the
130         # `MBRDisjoint` function doesn't work properly (I went down
131         # to the SQL level for debugging and still got bogus answers).
132         #qs2 = State.objects.filter(poly__disjoint=ptown.point)
133         #self.assertEqual(1, qs2.count())
134         #self.assertEqual('Kansas', qs2[0].name)
135
136     def test05_equals(self):
137         "Testing the 'same_as' and 'equals' lookup types."
138         pnt = fromstr('POINT (-95.363151 29.763374)', srid=4326)
139         c1 = City.objects.get(point=pnt)
140         c2 = City.objects.get(point__same_as=pnt)
141         c3 = City.objects.get(point__equals=pnt)
142         for c in [c1, c2, c3]: self.assertEqual('Houston', c.name)
143
144     def test06_geometryfield(self):
145         "Testing GeometryField."
146         f1 = Feature(name='Point', geom=Point(1, 1))
147         f2 = Feature(name='LineString', geom=LineString((0, 0), (1, 1), (5, 5)))
148         f3 = Feature(name='Polygon', geom=Polygon(LinearRing((0, 0), (0, 5), (5, 5), (5, 0), (0, 0))))
149         f4 = Feature(name='GeometryCollection',
150                      geom=GeometryCollection(Point(2, 2), LineString((0, 0), (2, 2)),
151                                              Polygon(LinearRing((0, 0), (0, 5), (5, 5), (5, 0), (0, 0)))))
152         f1.save()
153         f2.save()
154         f3.save()
155         f4.save()
156
157         f_1 = Feature.objects.get(name='Point')
158         self.assertEqual(True, isinstance(f_1.geom, Point))
159         self.assertEqual((1.0, 1.0), f_1.geom.tuple)
160         f_2 = Feature.objects.get(name='LineString')
161         self.assertEqual(True, isinstance(f_2.geom, LineString))
162         self.assertEqual(((0.0, 0.0), (1.0, 1.0), (5.0, 5.0)), f_2.geom.tuple)
163
164         f_3 = Feature.objects.get(name='Polygon')
165         self.assertEqual(True, isinstance(f_3.geom, Polygon))
166         f_4 = Feature.objects.get(name='GeometryCollection')
167         self.assertEqual(True, isinstance(f_4.geom, GeometryCollection))
168         self.assertEqual(f_3.geom, f_4.geom[2])
169    
170     def test07_mysql_limitations(self):
171         "Testing that union(), kml(), gml() raise exceptions."
172         self.assertRaises(ImproperlyConfigured, City.objects.union, Point(5, 23), field_name='point')
173         self.assertRaises(ImproperlyConfigured, State.objects.all().kml, field_name='poly')
174         self.assertRaises(ImproperlyConfigured, Country.objects.all().gml, field_name='mpoly')
175
176 def suite():
177     s = unittest.TestSuite()
178     s.addTest(unittest.makeSuite(GeoModelTest))
179     return s
Note: See TracBrowser for help on using the browser.