Changeset 6980
- Timestamp:
- 12/29/07 01:48:08 (8 months ago)
- Files:
-
- django/branches/gis/django/contrib/gis/tests/layermap/counties (added)
- django/branches/gis/django/contrib/gis/tests/layermap/counties/counties.dbf (added)
- django/branches/gis/django/contrib/gis/tests/layermap/counties/counties.shp (added)
- django/branches/gis/django/contrib/gis/tests/layermap/counties/counties.shx (added)
- django/branches/gis/django/contrib/gis/tests/layermap/models.py (modified) (3 diffs)
- django/branches/gis/django/contrib/gis/tests/layermap/tests.py (modified) (3 diffs)
- django/branches/gis/django/contrib/gis/utils/layermapping.py (modified) (7 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
django/branches/gis/django/contrib/gis/tests/layermap/models.py
r6708 r6980 1 1 from django.contrib.gis.db import models 2 3 class County(models.Model): 4 name = models.CharField(max_length=25) 5 mpoly = models.MultiPolygonField(srid=4269) # Multipolygon in NAD83 6 objects = models.GeoManager() 7 8 class CountyFeat(models.Model): 9 name = models.CharField(max_length=25) 10 poly = models.PolygonField(srid=4269) 11 objects = models.GeoManager() 2 12 3 13 class City(models.Model): … … 14 24 path = models.LineStringField() 15 25 objects = models.GeoManager() 16 17 # Mapping dictionary for the City model. 26 27 # Mapping dictionaries for the models above. 28 co_mapping = {'name' : 'Name', 29 'mpoly' : 'MULTIPOLYGON', # Will convert POLYGON features into MULTIPOLYGONS. 30 } 31 32 cofeat_mapping = {'name' : 'Name', 33 'poly' : 'POLYGON', 34 } 35 18 36 city_mapping = {'name' : 'Name', 19 37 'population' : 'Population', … … 23 41 } 24 42 25 # Mapping dictionary for the Interstate model.26 43 inter_mapping = {'name' : 'Name', 27 44 'length' : 'Length', django/branches/gis/django/contrib/gis/tests/layermap/tests.py
r6708 r6980 3 3 from datetime import date 4 4 from decimal import Decimal 5 from models import City, Interstate, city_mapping, inter_mapping5 from models import City, County, CountyFeat, Interstate, city_mapping, co_mapping, cofeat_mapping, inter_mapping 6 6 from django.contrib.gis.utils.layermapping import LayerMapping, LayerMapError, InvalidDecimal 7 7 from django.contrib.gis.gdal import DataSource … … 9 9 shp_path = os.path.dirname(__file__) 10 10 city_shp = os.path.join(shp_path, 'cities/cities.shp') 11 co_shp = os.path.join(shp_path, 'counties/counties.shp') 11 12 inter_shp = os.path.join(shp_path, 'interstates/interstates.shp') 12 13 … … 111 112 self.assertAlmostEqual(p1[1], p2[1], 6) 112 113 114 def test04_layermap_unique_multigeometry(self): 115 "Testing the `unique`, and `transform` keywords and geometry collection conversion." 116 # All the following should work. 117 try: 118 # Telling LayerMapping that we want no transformations performed on the data. 119 lm = LayerMapping(County, co_shp, co_mapping, transform=False) 120 121 # Specifying the source spatial reference system via the `source_srs` keyword. 122 lm = LayerMapping(County, co_shp, co_mapping, source_srs=4269) 123 lm = LayerMapping(County, co_shp, co_mapping, source_srs='NAD83') 124 125 # Unique may take tuple or string parameters. 126 for arg in ('name', ('name', 'mpoly')): 127 lm = LayerMapping(County, co_shp, co_mapping, transform=False, unique=arg) 128 except: 129 self.fail('No exception should be raised for proper use of keywords.') 130 131 # Testing invalid params for the `unique` keyword. 132 for e, arg in ((TypeError, 5.0), (ValueError, 'foobar'), (ValueError, ('name', 'mpolygon'))): 133 self.assertRaises(e, LayerMapping, County, co_shp, co_mapping, transform=False, unique=arg) 134 135 # No source reference system defined in the shapefile, should raise an error. 136 self.assertRaises(LayerMapError, LayerMapping, County, co_shp, co_mapping) 137 138 # If a mapping is specified as a collection, all OGR fields that 139 # are not collections will be converted into them. For example, 140 # a Point column would be converted to MultiPoint. Other things being done 141 # w/the keyword args: 142 # `transform=False`: Specifies that no transform is to be done; this 143 # has the effect of ignoring the spatial reference check (because the 144 # county shapefile does not have implicit spatial reference info). 145 # 146 # `unique='name'`: Creates models on the condition that they have 147 # unique county names; geometries from each feature however will be 148 # appended to the geometry collection of the unique model. Thus, 149 # all of the various islands in Honolulu county will be in in one 150 # database record with a MULTIPOLYGON type. 151 lm = LayerMapping(County, co_shp, co_mapping, transform=False, unique='name', silent=True) 152 lm.save() 153 154 # A reference that doesn't use the unique keyword; a new database record will 155 # created for each polygon. 156 lm = LayerMapping(CountyFeat, co_shp, cofeat_mapping, transform=False, silent=True) 157 lm.save() 158 159 # Dictionary to hold what's expected in the shapefile. 160 exp = {'names' : ('Bexar', 'Galveston', 'Harris', 'Honolulu', 'Pueblo'), 161 'num' : (1, 2, 2, 19, 1), # Number of polygons for each. 162 } 163 for name, n in zip(exp['names'], exp['num']): 164 c = County.objects.get(name=name) # Should only be one record. 165 self.assertEqual(n, len(c.mpoly)) 166 qs = CountyFeat.objects.filter(name=name) 167 self.assertEqual(n, qs.count()) 168 113 169 def suite(): 114 170 s = unittest.TestSuite() django/branches/gis/django/contrib/gis/utils/layermapping.py
r6708 r6980 64 64 transform: 65 65 Setting this to False will disable all coordinate transformations. 66 67 unique: 68 Setting this to the name, or a tuple of names, from the given 69 model will create models unique only to the given name(s). 70 Geometries will from each feature will be added into the collection 71 associated with the unique model. Forces transaction mode to 72 be 'autocommit'. 66 73 67 74 Example: … … 183 190 source_srs=None, encoding=None, check=True, 184 191 progress=False, interval=1000, strict=False, silent=False, 185 transaction_mode='commit_on_success', transform=True): 192 transaction_mode='commit_on_success', transform=True, 193 unique=False): 186 194 "Takes the Django model, the data source, and the mapping (dictionary)" 187 195 … … 209 217 # the coordinate transformation object (unless the `transform` 210 218 # keyword is set to False) 211 self.source_srs = self.check_srs(source_srs) 212 self.transform = transform and self.coord_transform() 219 if transform: 220 self.source_srs = self.check_srs(source_srs) 221 self.transform = self.coord_transform() 222 else: 223 self.transform = transform 213 224 214 225 # Checking the layer -- intitialization of the object will fail if … … 232 243 else: 233 244 self.encoding = None 245 246 if unique: 247 self.check_unique(unique) 248 transaction_mode = 'autocommit' # Has to be set to autocommit. 249 self.unique = unique 250 else: 251 self.unique = None 234 252 235 253 # Setting the transaction decorator with the function in the … … 314 332 else: 315 333 return sr 334 335 def check_unique(self, unique): 336 "Checks the `unique` keyword parameter -- may be a sequence or string." 337 # Getting the geometry field; only the first encountered GeometryField 338 # will be used. 339 self.geom_field = False 340 for model_field, ogr_fld in self.mapping.items(): 341 if ogr_fld in self.OGC_TYPES: 342 self.geom_field = model_field 343 break 344 345 if isinstance(unique, (list, tuple)): 346 # List of fields to determine uniqueness with 347 for attr in unique: 348 if not attr in self.mapping: raise ValueError 349 elif isinstance(unique, basestring): 350 # Only a single field passed in. 351 if unique not in self.mapping: raise ValueError 352 else: 353 raise TypeError('Unique keyword argument must be set with a tuple, list, or string.') 316 354 317 355 def coord_transform(self): … … 371 409 372 410 return kwargs, all_prepped 411 412 def unique_kwargs(self, kwargs): 413 """ 414 Given the feature keyword arguments (from `feature_kwargs`) this routine 415 will construct and return the uniqueness keyword arguments -- a subset 416 of the feature kwargs. 417 """ 418 if isinstance(self.unique, basestring): 419 return {self.unique : kwargs[self.unique]} 420 else: 421 return dict((fld, kwargs[fld]) for fld in self.unique) 373 422 374 423 def verify_field(self, fld, model_field): … … 486 535 # Constructing the model using the keyword args 487 536 if all_prepped: 488 m = self.model(**kwargs) 537 if self.unique: 538 # If we want unique models on a particular field, handle the 539 # geometry appropriately. 540 try: 541 # Getting the keyword arguments and retrieving 542 # the unique model. 543 u_kwargs = self.unique_kwargs(kwargs) 544 m = self.model.objects.get(**u_kwargs) 545 546 # Getting the geometry (in OGR form), creating 547 # one from the kwargs WKT, adding in additional 548 # geometries, and update the attribute with the 549 # just-updated geometry WKT. 550 geom = getattr(m, self.geom_field).ogr 551 new = OGRGeometry(kwargs[self.geom_field]) 552 for g in new: geom.add(g) 553 setattr(m, self.geom_field, geom.wkt) 554 except ObjectDoesNotExist: 555 # No unique model exists yet, create. 556 m = self.model(**kwargs) 557 else: 558 m = self.model(**kwargs) 559 489 560 try: 561 # Attempting to save. 490 562 m.save() 491 563 num_saved += 1
