diff --git a/django/contrib/gis/tests/layermap/interstates/interstates.dbf b/django/contrib/gis/tests/layermap/interstates/interstates.dbf index 7b551461da..a88d171588 100644 Binary files a/django/contrib/gis/tests/layermap/interstates/interstates.dbf and b/django/contrib/gis/tests/layermap/interstates/interstates.dbf differ diff --git a/django/contrib/gis/tests/layermap/interstates/interstates.shp b/django/contrib/gis/tests/layermap/interstates/interstates.shp index 57de1e7dc5..6d93de75ec 100644 Binary files a/django/contrib/gis/tests/layermap/interstates/interstates.shp and b/django/contrib/gis/tests/layermap/interstates/interstates.shp differ diff --git a/django/contrib/gis/tests/layermap/interstates/interstates.shx b/django/contrib/gis/tests/layermap/interstates/interstates.shx index a277b98449..7b9088ac5b 100644 Binary files a/django/contrib/gis/tests/layermap/interstates/interstates.shx and b/django/contrib/gis/tests/layermap/interstates/interstates.shx differ diff --git a/django/contrib/gis/tests/layermap/models.py b/django/contrib/gis/tests/layermap/models.py index 512cdb42af..6b575f5c46 100644 --- a/django/contrib/gis/tests/layermap/models.py +++ b/django/contrib/gis/tests/layermap/models.py @@ -10,7 +10,7 @@ class City(models.Model): class Interstate(models.Model): name = models.CharField(max_length=20) - length = models.DecimalField(max_digits=7, decimal_places=2) + length = models.DecimalField(max_digits=6, decimal_places=2) path = models.LineStringField() objects = models.GeoManager() diff --git a/django/contrib/gis/tests/layermap/tests.py b/django/contrib/gis/tests/layermap/tests.py index c7e67a63c0..825e3d7e69 100644 --- a/django/contrib/gis/tests/layermap/tests.py +++ b/django/contrib/gis/tests/layermap/tests.py @@ -88,17 +88,27 @@ class LayerMapTest(unittest.TestCase): lm = LayerMapping(Interstate, inter_shp, inter_mapping, silent=True) lm.save() - # Only one interstate should have imported correctly. - self.assertEqual(1, Interstate.objects.count()) + # Two interstate should have imported correctly. + self.assertEqual(2, Interstate.objects.count()) - # Verifying the values in the single feature w/the model. + # Verifying the values in the layer w/the model. ds = DataSource(inter_shp) - feat = ds[0][0] - istate = Interstate.objects.get(name=feat['Name'].value) - self.assertEqual(Decimal(str(feat['Length'])), istate.length) - for p1, p2 in zip(feat.geom, istate.path): - self.assertAlmostEqual(p1[0], p2[0], 6) - self.assertAlmostEqual(p1[1], p2[1], 6) + + # Only the first two features of this shapefile are valid. + valid_feats = ds[0][:2] + for feat in valid_feats: + istate = Interstate.objects.get(name=feat['Name'].value) + + if feat.fid == 0: + self.assertEqual(Decimal(str(feat['Length'])), istate.length) + elif feat.fid == 1: + # Everything but the first two decimal digits were truncated, + # because the Interstate model's `length` field has decimal_places=2. + self.assertAlmostEqual(feat.get('Length'), float(istate.length), 2) + + for p1, p2 in zip(feat.geom, istate.path): + self.assertAlmostEqual(p1[0], p2[0], 6) + self.assertAlmostEqual(p1[1], p2[1], 6) def suite(): s = unittest.TestSuite() diff --git a/django/contrib/gis/utils/layermapping.py b/django/contrib/gis/utils/layermapping.py index 9534d86082..65b855bbc2 100644 --- a/django/contrib/gis/utils/layermapping.py +++ b/django/contrib/gis/utils/layermapping.py @@ -394,11 +394,27 @@ class LayerMapping(object): d = Decimal(str(fld.value)) except: raise InvalidDecimal('Could not construct decimal from: %s' % fld) + + # Getting the decimal value as a tuple. dtup = d.as_tuple() - if len(dtup[1]) > field_class.max_digits: - raise InvalidDecimal('More than the maximum # of digits encountered.') - elif len(dtup[1][dtup[2]:]) > field_class.decimal_places: - raise InvalidDecimal('More than the maximum # of decimal places encountered.') + digits = dtup[1] + d_idx = dtup[2] # index where the decimal is + + # Maximum amount of precision, or digits to the left of the decimal. + max_prec = field_class.max_digits - field_class.decimal_places + + # Getting the digits to the left of the decimal place for the + # given decimal. + if d_idx < 0: + n_prec = len(digits[:d_idx]) + else: + n_prec = len(digits) + d_idx + + # If we have more than the maximum digits allowed, then throw an + # InvalidDecimal exception. + if n_prec > max_prec: + raise InvalidDecimal('A DecimalField with max_digits %d, decimal_places %d must round to an absolute value less than 10^%d.' % + (field_class.max_digits, field_class.decimal_places, max_prec)) val = d else: val = fld.value @@ -467,7 +483,7 @@ class LayerMapping(object): elif not self.silent: print 'Ignoring Feature ID %s because: %s' % (feat.fid, msg) else: - # Constructing the model using the constructed keyword args + # Constructing the model using the keyword args if all_prepped: m = self.model(**kwargs) try: