Opened 8 years ago

Closed 7 years ago

#15271 closed Bug (fixed)

django.contrib.gis.forms.fields.GeometryField should call to_python before cleaning

Reported by: Daniel Barreto Owned by: nobody
Component: GIS Version: master
Severity: Normal Keywords: gis, field, clean, to_python
Cc: Triage Stage: Accepted
Has patch: yes Needs documentation: no
Needs tests: yes Patch needs improvement: no
Easy pickings: no UI/UX: no


GeometryField overrides the default clean method for Field class and doesn't take in account the call to to_python before cleaning of the value.
This is important because when using GeometryFields in a form you could want to render it with a MultiWidget, for example:

Let's say we create a PointField (which inherits from GeometryField) with a MultiWidget that renders to FloatFields (one for each coordinate). This widget will return a list with both float values as its value, and that's what will be passed to the clean method. On every other field, we know that this list will be passed to to_python before calling clean, but with GeometryField that's not the case.

Following that example, you could redefine the to_python method in our new PointField class to check if the value is instance of a tuple/list (like it's done in a DateTimeField), and transform it to a string representing the Point WKT formed with the two values of that list, but you will also have to redefine clean method to call to_python first and then do the cleaning.

I'm submitting a simple patch to fix this.

Attachments (3)

0001-Added-to_python-to-GeometryField-which-transform-the.patch (1.8 KB) - added by Daniel Barreto 8 years ago.
0001-Tests-for-GeometryField.to_python-method.patch (2.1 KB) - added by Daniel Barreto 8 years ago.
15271.diff (2.8 KB) - added by Colin Copeland 7 years ago.

Download all attachments as: .zip

Change History (10)

comment:1 Changed 8 years ago by Russell Keith-Magee

Needs tests: set
Triage Stage: UnreviewedAccepted

Changed 8 years ago by Daniel Barreto

comment:2 Changed 8 years ago by Daniel Barreto

just added a patch for the new method tests. I don't know if more tests are required, I think they're pretty much covered by the clean method tests.

comment:3 Changed 8 years ago by Łukasz Rekucki

Severity: Normal
Type: Bug

comment:4 Changed 7 years ago by Colin Copeland

Easy pickings: unset
Owner: changed from nobody to Colin Copeland
Status: newassigned
UI/UX: unset

comment:5 Changed 7 years ago by Colin Copeland

To illustrate volrath's suggested changes, the provided patch would allow you to do something along the lines of this:

from django import forms
from django.contrib.gis.forms import GeometryField

class CoordsWidget(forms.MultiWidget):

    def __init__(self, *args, **kwargs):
        widgets = (forms.TextInput(), forms.TextInput())
        super(CoordsWidget, self).__init__(widgets, *args, **kwargs)

    def decompress(self, value):
        return value.coords

class CoordsField(GeometryField):
    widget = CoordsWidget

    def to_python(self, value):
        wkt = "POINT({0} {1})".format(value[0], value[1])
        return super(CoordsField, self).to_python(wkt)

class LocationForm(forms.ModelForm):

    point = CoordsField()

    class Meta(object):
        model = Location

I'll consolidate the separate patches into a single file.

Last edited 7 years ago by Colin Copeland (previous) (diff)

Changed 7 years ago by Colin Copeland

Attachment: 15271.diff added

comment:6 Changed 7 years ago by Colin Copeland

Owner: changed from Colin Copeland to nobody
Status: assignednew

I reviewed volrath's patches and consolidated them into a single file. I also created a pull request here:

comment:7 Changed 7 years ago by Claude Paroz <claude@…>

Resolution: fixed
Status: newclosed

In [41eb70f7620dbae43bb72f265489fa3ac19c5c66]:

Fixed #15271 -- Defined a to_python method for GeometryField

Thanks volrath and copelco for their work on the patch.

Note: See TracTickets for help on using tickets.
Back to Top