from django import forms from django.utils.translation import ugettext_lazy as _ # While this couples the geographic forms to the GEOS library, # it decouples from database (by not importing SpatialBackend). from django.contrib.gis.geos import GEOSGeometry class GeometryField(forms.Field): """ This is the basic form field for a Geometry. Any textual input that is accepted by GEOSGeometry is accepted by this form. By default, this includes WKT, HEXEWKB, WKB (in a buffer), and GeoJSON. """ widget = forms.Textarea default_error_messages = { 'no_geom' : _(u'No geometry value provided.'), 'invalid_geom' : _(u'Invalid geometry value.'), 'invalid_geom_type' : _(u'Invalid geometry type.'), 'transform_error' : _(u'An error occurred when transforming the geometry ' 'to the SRID of the geometry form field.'), } def __init__(self, **kwargs): # Pop out attributes from the database field, or use sensible # defaults (e.g., allow None). self.srid = kwargs.pop('srid', None) self.geom_type = kwargs.pop('geom_type', 'GEOMETRY') self.null = kwargs.pop('null', True) super(GeometryField, self).__init__(**kwargs) def clean(self, value): """ Validates that the input value can be converted to a Geometry object (which is returned). A ValidationError is raised if the value cannot be instantiated as a Geometry. """ if not value: if self.null and not self.required: # The geometry column allows NULL and is not required. return None else: raise forms.ValidationError(self.error_messages['no_geom']) # Trying to create a Geometry object from the form value. try: geom = GEOSGeometry(value) except: raise forms.ValidationError(self.error_messages['invalid_geom']) # Ensuring that the geometry is of the correct type (indicated # using the OGC string label). if str(geom.geom_type).upper() != self.geom_type and not self.geom_type == 'GEOMETRY': raise forms.ValidationError(self.error_messages['invalid_geom_type']) # Transforming the geometry if the SRID was set. if self.srid: if not geom.srid: # Should match that of the field if not given. geom.srid = self.srid elif self.srid != -1 and self.srid != geom.srid: try: geom.transform(self.srid) except: raise forms.ValidationError(self.error_messages['transform_error']) return geom