Opened 6 years ago

Closed 4 years ago

#15271 closed Bug (fixed)

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

Reported by: volrath 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 volrath 6 years ago.
0001-Tests-for-GeometryField.to_python-method.patch (2.1 KB) - added by volrath 6 years ago.
15271.diff (2.8 KB) - added by copelco 5 years ago.

Download all attachments as: .zip

Change History (10)

comment:1 Changed 6 years ago by russellm

  • Needs documentation unset
  • Needs tests set
  • Patch needs improvement unset
  • Triage Stage changed from Unreviewed to Accepted

comment:2 Changed 6 years ago by volrath

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 5 years ago by lrekucki

  • Severity set to Normal
  • Type set to Bug

comment:4 Changed 5 years ago by copelco

  • Easy pickings unset
  • Owner changed from nobody to copelco
  • Status changed from new to assigned
  • UI/UX unset

comment:5 Changed 5 years ago by copelco

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
Version 0, edited 5 years ago by copelco (next)

Changed 5 years ago by copelco

comment:6 Changed 5 years ago by copelco

  • Owner changed from copelco to nobody
  • Status changed from assigned to new

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

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

  • Resolution set to fixed
  • Status changed from new to closed

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