Question on cleaning ModelForms

10 views
Skip to first unread message

Jeff Heard

unread,
Oct 17, 2011, 3:30:35 PM10/17/11
to django...@googlegroups.com
class FarmersMarket(ModelForm):
class Meta:
model = models.FarmersMarket
exclude = ('location',)

def clean(self):
place, (lat, lng) = _g.geocode(self.cleaned_data['address'])
self.cleaned_data['location'] = Point(lng,lat)
return self.cleaned_data

----

Here's my code minus the exception handling. Now what I *want* to
have happen is that the models.FarmersMarket.location field on the
model is set sometime shortly after the form is submitted by the user,
by way of geocoding the data, rather than having them tediously enter
a POINT wkt string in the textarea field. So my idea was to put a
call to geopy.Google.geocode in FarmersMarket.self.clean. I can
confirm clean() is getting called, but for some reason, the 'location'
field isn't being set in the model. I get a whine from Django that
the location field cannot be NULL (which is true, it can't).

Can anyone tell me how I'm supposed to be doing this? I want them to
enter an address on the form, not a latitude/longitude pair.

-- Jeff

Brian Bouterse

unread,
Oct 17, 2011, 4:26:31 PM10/17/11
to django...@googlegroups.com
I've done it before using a post save signal, although I had lat,lng = NULL in the schema so that differs from your request here.  After saving, I would issue an update.  I forget why I didn't use a pre-save signal.

Aside from signals, you may also be able to use a model field default with a callable to set the lat/lng of the FarmersMarket object.  It's an idea I haven't tested, so I'm not positive it will work.

You could write some geocoding middleware that sets request.POST data in some way as it passes through.  I don't really like this solution since it is kind of "magical."

Brian


--
You received this message because you are subscribed to the Google Groups "Django users" group.
To post to this group, send email to django...@googlegroups.com.
To unsubscribe from this group, send email to django-users...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/django-users?hl=en.




--
Brian Bouterse
ITng Services

Daniel Roseman

unread,
Oct 18, 2011, 4:52:42 AM10/18/11
to django...@googlegroups.com
The point is, you've told Django that `location` isn't a field on this form, by specifying it in `exclude`. So Django doesn't take any notice of the extra element you've added in cleaned_data.

The way to do this is to override the form's save method and do it there:

    def save(self, commit=False):
        market = super(FarmersMarket, self).save(commit=False)
        place, (lat, lng) = _g.geocode(market.address)
        market.location = Point(lng,lat)
        if commit:
            market.save()
        return market

--
DR.
         

Jeff Heard

unread,
Oct 18, 2011, 9:00:20 AM10/18/11
to django...@googlegroups.com
But I want to be able to invalidate my form if geocoding fails...  Can I still do that in the save method?


--
You received this message because you are subscribed to the Google Groups "Django users" group.
To view this discussion on the web visit https://groups.google.com/d/msg/django-users/-/3LiBsqFIJYoJ.

Tom Evans

unread,
Oct 18, 2011, 9:20:29 AM10/18/11
to django...@googlegroups.com
On Tue, Oct 18, 2011 at 2:00 PM, Jeff Heard <jefferso...@gmail.com> wrote:
> But I want to be able to invalidate my form if geocoding fails...  Can I
> still do that in the save method?
>

No, save() is not part of validation. However, it is not hard to
combine the two:

In the clean() method, calculate the geocoding point and store it in
an attribute of the form. In the save() method, populate the field as
shown by Daniel, but use the stored attribute value.

Cheers

Tom

Reply all
Reply to author
Forward
0 new messages