|
1 from django import forms |
|
2 from django.utils.translation import ugettext_lazy as _ |
|
3 |
|
4 # While this couples the geographic forms to the GEOS library, |
|
5 # it decouples from database (by not importing SpatialBackend). |
|
6 from django.contrib.gis.geos import GEOSGeometry |
|
7 |
|
8 class GeometryField(forms.Field): |
|
9 """ |
|
10 This is the basic form field for a Geometry. Any textual input that is |
|
11 accepted by GEOSGeometry is accepted by this form. By default, |
|
12 this includes WKT, HEXEWKB, WKB (in a buffer), and GeoJSON. |
|
13 """ |
|
14 widget = forms.Textarea |
|
15 |
|
16 default_error_messages = { |
|
17 'no_geom' : _(u'No geometry value provided.'), |
|
18 'invalid_geom' : _(u'Invalid geometry value.'), |
|
19 'invalid_geom_type' : _(u'Invalid geometry type.'), |
|
20 'transform_error' : _(u'An error occurred when transforming the geometry ' |
|
21 'to the SRID of the geometry form field.'), |
|
22 } |
|
23 |
|
24 def __init__(self, **kwargs): |
|
25 # Pop out attributes from the database field, or use sensible |
|
26 # defaults (e.g., allow None). |
|
27 self.srid = kwargs.pop('srid', None) |
|
28 self.geom_type = kwargs.pop('geom_type', 'GEOMETRY') |
|
29 self.null = kwargs.pop('null', True) |
|
30 super(GeometryField, self).__init__(**kwargs) |
|
31 |
|
32 def clean(self, value): |
|
33 """ |
|
34 Validates that the input value can be converted to a Geometry |
|
35 object (which is returned). A ValidationError is raised if |
|
36 the value cannot be instantiated as a Geometry. |
|
37 """ |
|
38 if not value: |
|
39 if self.null and not self.required: |
|
40 # The geometry column allows NULL and is not required. |
|
41 return None |
|
42 else: |
|
43 raise forms.ValidationError(self.error_messages['no_geom']) |
|
44 |
|
45 # Trying to create a Geometry object from the form value. |
|
46 try: |
|
47 geom = GEOSGeometry(value) |
|
48 except: |
|
49 raise forms.ValidationError(self.error_messages['invalid_geom']) |
|
50 |
|
51 # Ensuring that the geometry is of the correct type (indicated |
|
52 # using the OGC string label). |
|
53 if str(geom.geom_type).upper() != self.geom_type and not self.geom_type == 'GEOMETRY': |
|
54 raise forms.ValidationError(self.error_messages['invalid_geom_type']) |
|
55 |
|
56 # Transforming the geometry if the SRID was set. |
|
57 if self.srid: |
|
58 if not geom.srid: |
|
59 # Should match that of the field if not given. |
|
60 geom.srid = self.srid |
|
61 elif self.srid != -1 and self.srid != geom.srid: |
|
62 try: |
|
63 geom.transform(self.srid) |
|
64 except: |
|
65 raise forms.ValidationError(self.error_messages['transform_error']) |
|
66 |
|
67 return geom |