CBV FormView get_form_kwargs() doesn't.... when request.method == "GET"

960 views
Skip to first unread message

Daniel Swarbrick

unread,
Jan 12, 2011, 12:54:45 PM1/12/11
to Django developers
Most of the time, I use POST for forms, but using GET is useful when
developing a search form, for example. This is especially true if you
want to paginate your results, because you still have all your
original form variables in the query string.

CBV FormView get_form_kwargs() only populates form_kwargs data if the
request is POST or PUT, which means that a GET form will never have
form.is_valid() == True, even thought the supplied query string may
indeed validate all form fields.

Is this by design, or an oversight?

I'm working around this for now by overriding get_form_kwargs() in my
view like so:

def get_form_kwargs(self):
kwargs = {'initial': self.get_initial()}
if self.request.GET:
kwargs['data'] = self.request.GET
return kwargs

If the view is requested with no query string, request.GET will be
empty, and thus kwargs will not have 'data' key. Consequently,
form.is_valid() returns False. If I submit the form though, and the
view is request with a URL query string, kwargs['data'] gets set to
request.GET, and form.is_valid() returns True (if the values satisfy
the various form clean_foo() methods.

Andrew Godwin

unread,
Jan 12, 2011, 6:19:06 PM1/12/11
to django-d...@googlegroups.com
On 12/01/11 17:54, Daniel Swarbrick wrote:
> Most of the time, I use POST for forms, but using GET is useful when
> developing a search form, for example. This is especially true if you
> want to paginate your results, because you still have all your
> original form variables in the query string.
>
> CBV FormView get_form_kwargs() only populates form_kwargs data if the
> request is POST or PUT, which means that a GET form will never have
> form.is_valid() == True, even thought the supplied query string may
> indeed validate all form fields.
>
> Is this by design, or an oversight?

This is, at least in my view, by design - it's good web behaviour to not
use GET to modify data, or otherwise do things that forms usually end up
doing.

> I'm working around this for now by overriding get_form_kwargs() in my
> view like so:
>
> def get_form_kwargs(self):
> kwargs = {'initial': self.get_initial()}
> if self.request.GET:
> kwargs['data'] = self.request.GET
> return kwargs

This is the point about class-based views - you can just add that as a
Mixin or a new base class, and get the functionality on the views you want.

I'm -1 on the generic views accepting GET for form submissions, for the
GET-modifying-data-is-bad reasons above. That doesn't, however, stop you
from using it as a mixin, and if you find any design issues with mixing
in new behaviours, I'll be more than happy to take a look...

Andrew

Tom Evans

unread,
Jan 24, 2011, 5:54:36 AM1/24/11
to django-d...@googlegroups.com
On Wed, Jan 12, 2011 at 11:19 PM, Andrew Godwin <and...@aeracode.org> wrote:
> On 12/01/11 17:54, Daniel Swarbrick wrote:
>> Most of the time, I use POST for forms, but using GET is useful when
>> developing a search form, for example. This is especially true if you
>> want to paginate your results, because you still have all your
>> original form variables in the query string.
>>
>> CBV FormView get_form_kwargs() only populates form_kwargs data if the
>> request is POST or PUT, which means that a GET form will never have
>> form.is_valid() == True, even thought the supplied query string may
>> indeed validate all form fields.
>>
>> Is this by design, or an oversight?
>
> This is, at least in my view, by design - it's good web behaviour to not
> use GET to modify data, or otherwise do things that forms usually end up
> doing.
>

True. Not all forms do that though. The OPs case seems reasonable
enough, all 'search'-like forms *should* be submitted through GET
requests. Examples from django's own websites include the custom
google search box on docs.djangoproject.com, the TRAC ticket search on
code.djangoproject.com, etc.

It seems strange to say that these sorts of forms are not usable in a
FormView without modification. Perhaps some additional documentation
should be added to [1] to document this limitation.

Cheers

Tom

[1] http://docs.djangoproject.com/en/dev/ref/class-based-views/#formview

Reply all
Reply to author
Forward
0 new messages