~ubuntu-branches/debian/sid/python-django/sid

« back to all changes in this revision

Viewing changes to django/contrib/gis/forms/fields.py

  • Committer: Package Import Robot
  • Author(s): Luke Faraone
  • Date: 2013-11-07 15:33:49 UTC
  • mfrom: (1.3.12)
  • Revision ID: package-import@ubuntu.com-20131107153349-e31sc149l2szs3jb
Tags: 1.6-1
* New upstream version. Closes: #557474, #724637.
* python-django now also suggests the installation of ipython,
  bpython, python-django-doc, and libgdal1.
  Closes: #636511, #686333, #704203
* Set package maintainer to Debian Python Modules Team.
* Bump standards version to 3.9.5, no changes needed.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
from __future__ import unicode_literals
2
2
 
 
3
import warnings
 
4
 
3
5
from django import forms
 
6
from django.utils import six
4
7
from django.utils.translation import ugettext_lazy as _
5
8
 
6
9
# While this couples the geographic forms to the GEOS library,
7
10
# it decouples from database (by not importing SpatialBackend).
8
 
from django.contrib.gis.geos import GEOSException, GEOSGeometry
 
11
from django.contrib.gis.geos import GEOSException, GEOSGeometry, fromstr
 
12
from .widgets import OpenLayersWidget
 
13
 
9
14
 
10
15
class GeometryField(forms.Field):
11
16
    """
13
18
    accepted by GEOSGeometry is accepted by this form.  By default,
14
19
    this includes WKT, HEXEWKB, WKB (in a buffer), and GeoJSON.
15
20
    """
16
 
    widget = forms.Textarea
 
21
    widget = OpenLayersWidget
 
22
    geom_type = 'GEOMETRY'
17
23
 
18
24
    default_error_messages = {
19
 
        'no_geom' : _('No geometry value provided.'),
 
25
        'required' : _('No geometry value provided.'),
20
26
        'invalid_geom' : _('Invalid geometry value.'),
21
27
        'invalid_geom_type' : _('Invalid geometry type.'),
22
28
        'transform_error' : _('An error occurred when transforming the geometry '
27
33
        # Pop out attributes from the database field, or use sensible
28
34
        # defaults (e.g., allow None).
29
35
        self.srid = kwargs.pop('srid', None)
30
 
        self.geom_type = kwargs.pop('geom_type', 'GEOMETRY')
31
 
        self.null = kwargs.pop('null', True)
 
36
        self.geom_type = kwargs.pop('geom_type', self.geom_type)
 
37
        if 'null' in kwargs:
 
38
            kwargs.pop('null', True)
 
39
            warnings.warn("Passing 'null' keyword argument to GeometryField is deprecated.",
 
40
                DeprecationWarning, stacklevel=2)
32
41
        super(GeometryField, self).__init__(**kwargs)
 
42
        self.widget.attrs['geom_type'] = self.geom_type
33
43
 
34
44
    def to_python(self, value):
35
45
        """
36
46
        Transforms the value to a Geometry object.
37
47
        """
38
 
        try:
39
 
            return GEOSGeometry(value)
40
 
        except (GEOSException, ValueError, TypeError):
41
 
            raise forms.ValidationError(self.error_messages['invalid_geom'])
 
48
        if value in self.empty_values:
 
49
            return None
 
50
 
 
51
        if not isinstance(value, GEOSGeometry):
 
52
            try:
 
53
                value = GEOSGeometry(value)
 
54
                if not value.srid:
 
55
                    value.srid = self.widget.map_srid
 
56
            except (GEOSException, ValueError, TypeError):
 
57
                raise forms.ValidationError(self.error_messages['invalid_geom'], code='invalid_geom')
 
58
        return value
42
59
 
43
60
    def clean(self, value):
44
61
        """
46
63
        object (which is returned).  A ValidationError is raised if
47
64
        the value cannot be instantiated as a Geometry.
48
65
        """
49
 
        if not value:
50
 
            if self.null and not self.required:
51
 
                # The geometry column allows NULL and is not required.
52
 
                return None
53
 
            else:
54
 
                raise forms.ValidationError(self.error_messages['no_geom'])
55
 
 
56
 
        # Transform the value to a python object first
57
 
        geom = self.to_python(value)
 
66
        geom = super(GeometryField, self).clean(value)
 
67
        if geom is None:
 
68
            return geom
58
69
 
59
70
        # Ensuring that the geometry is of the correct type (indicated
60
71
        # using the OGC string label).
61
72
        if str(geom.geom_type).upper() != self.geom_type and not self.geom_type == 'GEOMETRY':
62
 
            raise forms.ValidationError(self.error_messages['invalid_geom_type'])
 
73
            raise forms.ValidationError(self.error_messages['invalid_geom_type'], code='invalid_geom_type')
63
74
 
64
75
        # Transforming the geometry if the SRID was set.
65
76
        if self.srid:
70
81
                try:
71
82
                    geom.transform(self.srid)
72
83
                except:
73
 
                    raise forms.ValidationError(self.error_messages['transform_error'])
 
84
                    raise forms.ValidationError(self.error_messages['transform_error'], code='transform_error')
74
85
 
75
86
        return geom
 
87
 
 
88
    def _has_changed(self, initial, data):
 
89
        """ Compare geographic value of data with its initial value. """
 
90
 
 
91
        try:
 
92
            data = self.to_python(data)
 
93
            initial = self.to_python(initial)
 
94
        except ValidationError:
 
95
            return True
 
96
 
 
97
        # Only do a geographic comparison if both values are available
 
98
        if initial and data:
 
99
            data.transform(initial.srid)
 
100
            # If the initial value was not added by the browser, the geometry
 
101
            # provided may be slightly different, the first time it is saved.
 
102
            # The comparison is done with a very low tolerance.
 
103
            return not initial.equals_exact(data, tolerance=0.000001)
 
104
        else:
 
105
            # Check for change of state of existence
 
106
            return bool(initial) != bool(data)
 
107
 
 
108
 
 
109
class GeometryCollectionField(GeometryField):
 
110
    geom_type = 'GEOMETRYCOLLECTION'
 
111
 
 
112
 
 
113
class PointField(GeometryField):
 
114
    geom_type = 'POINT'
 
115
 
 
116
 
 
117
class MultiPointField(GeometryField):
 
118
    geom_type = 'MULTIPOINT'
 
119
 
 
120
 
 
121
class LineStringField(GeometryField):
 
122
    geom_type = 'LINESTRING'
 
123
 
 
124
 
 
125
class MultiLineStringField(GeometryField):
 
126
    geom_type = 'MULTILINESTRING'
 
127
 
 
128
 
 
129
class PolygonField(GeometryField):
 
130
    geom_type = 'POLYGON'
 
131
 
 
132
 
 
133
class MultiPolygonField(GeometryField):
 
134
    geom_type = 'MULTIPOLYGON'