Why can't forms access the request object?

42 views
Skip to first unread message

shacker

unread,
Mar 11, 2012, 4:32:39 AM3/11/12
to django...@googlegroups.com
I recently needed to access request.user in a form, and found that I couldn't. Found many articles describing ways to accomplish this, such as James Bennett's [1].

I did get it working, but I'm curious *why* the request object isn't accessible from forms as it is from views. Why do we need to override __init__  to accomplish this? Seems like the kind of thing Django could "take care of" for us.


Thanks to anyone who can clarify.

./s



Donald Stufft

unread,
Mar 11, 2012, 4:33:39 AM3/11/12
to django...@googlegroups.com
Forms aren't only usable from inside a view.
--
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/-/1z9ElVqpRucJ.
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.

Sergiy Khohlov

unread,
Mar 11, 2012, 9:24:30 AM3/11/12
to django...@googlegroups.com
Of course form does not have access to the object. But you can pass
some value which is accessible in view from view to form.
Separating task in 2 parts :

1) set initial values in view class

class myviewclass():
""" This is example only . full class realization is more complex """

form_class = myformclass
template_name = "mytemplate.html"

get_initial(self):
""" Passing initial values to the form"""

# At first initial data should be saved
super(myviewclass, self).get_initial()
# adding our value
self.initial= {"myuser": self.request.user}
return self.initial


Second part (form side)

myformclass():
""" This is really simple example. Perfect form is more complex"""
def __init__(self, *args, **kwargs):
# get our values from view
myvalues = kwargs.pop('initial', None)
#print it to console (this is a dict by default)
print myvalues
# and executing default constructor after this
super(myformclass, self).__init__(*args, **kwargs)

Thanks, Serge


2012/3/11 Donald Stufft <donald...@gmail.com>:

shacker

unread,
Mar 11, 2012, 12:43:55 PM3/11/12
to django...@googlegroups.com
On Sunday, March 11, 2012 6:24:30 AM UTC-7, skhohlov wrote:
Of course form  does not have access to the object.

skholov - Thanks, but you misunderstand my question. Again, I know that forms don't have access to request, and again, I've got it working already (though with a different approach - see my OP). My question was an attempt to understand the plumbing or the python better. To reiterate, I'd like to know WHY request isn't automatically available from forms, as it is from views. To put the question another way, when we define a view function, we do something like:

def edit(request,story_id):
  ...

But when we create a form, we can't just do:

class StoryForm(ModelForm, request):
  ...

It seems like this is the kind of thing Django could take care of for us - we shouldn't have to jump through hoops to get at request -  but there's probably a good reason why it works this way. Does my question make more sense now? 

Thanks,
Scot

Masklinn

unread,
Mar 11, 2012, 12:50:48 PM3/11/12
to django...@googlegroups.com
On 2012-03-11, at 17:43 , shacker wrote:
> On Sunday, March 11, 2012 6:24:30 AM UTC-7, skhohlov wrote:
>>
>> Of course form does not have access to the object.
>
>
> skholov - Thanks, but you misunderstand my question. Again, I know that
> forms don't have access to request, and again, I've got it working already
> (though with a different approach - see my OP). My question was an attempt
> to understand the plumbing or the python better. To reiterate, I'd like to
> know WHY request isn't automatically available from forms, as it is from
> views.

1. Because there are no paths to do it automatically, this would require
passing the request object to all forms explicitly

2. Because, as Donald noted, forms don't *need* a request object and
indeed can be used completely independently from the request/response
cycle (or from a given request).

3. Plus what would be the semantics there, would the form prime itself
using request.POST? request.GET? A combination of both? Only under some
request methods?

Views exist to handle requests, that's all their job is, so them
receiving a request object makes perfect sense. Not so for forms.

> To put the question another way, when we define a view function, we
> do something like:
>
> def edit(request,story_id):
> ...
>
> But when we create a form, we can't just do:
>
> class StoryForm(ModelForm, request):

> …

For what it's worth, this code makes absolutely no sense, it tries to
create a class which inherits from a request object (which is not in
scope and is not a type)


Donald Stufft

unread,
Mar 11, 2012, 12:53:20 PM3/11/12
to django...@googlegroups.com
On Sunday, March 11, 2012 at 12:43 PM, shacker wrote:
On Sunday, March 11, 2012 6:24:30 AM UTC-7, skhohlov wrote:
Of course form  does not have access to the object.

skholov - Thanks, but you misunderstand my question. Again, I know that forms don't have access to request, and again, I've got it working already (though with a different approach - see my OP). My question was an attempt to understand the plumbing or the python better. To reiterate, I'd like to know WHY request isn't automatically available from forms, as it is from views. To put the question another way, when we define a view function, we do something like:

def edit(request,story_id):
  ...
This is a function that get's passed request as it's first argument. Since view functions are _always_ run during the request response cycle of an HTTP request, request is always available to be passed into the view. 

But when we create a form, we can't just do:

class StoryForm(ModelForm, request):
  ...
This is subclassing the form from request. the equivalent code would be to accept the request in the forms __init__, 
however this would need to be option to still allow using the forms outside of the request, response cycle. This parameter
is very easy to add on your own and including it by default needlessly ties the form processing library to django requests.

It seems like this is the kind of thing Django could take care of for us - we shouldn't have to jump through hoops to get at request -  but there's probably a good reason why it works this way. Does my question make more sense now? 

Thanks,
Scot

--
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/-/8DXqXSX-YhAJ.

shacker

unread,
Mar 12, 2012, 2:23:49 AM3/12/12
to django...@googlegroups.com
Thanks for the explanations Masklinn and dstuffte - this makes a lot more sense now. I guess I was thinking of this in more simplistic terms - I was assuming that a form is always invoked from a view, so naturally it would inherit the request object. I'm having trouble thinking of  a use case where a  form would  not be part of any request/response cycle, but if that were true, then you're right - it would not be necessarily connected to request.  

Also, I see that part of the problem is that a view is a *function* and its  args  are passed context objects, while a form is a *class* and its  args are only what class it inherits from - so yeah, there's a semantics problem of how one would pass in request.

And you're right, it's not a hard problem to solve - just that the solution is a bit more verbose than I'd like it to be.  

Thanks again,
./s

Sergiy Khohlov

unread,
Mar 12, 2012, 3:47:17 AM3/12/12
to django...@googlegroups.com
Shacker,
Django migrates from function based view to the class based. It will
be nice to catch a good resource about class view usage because
official documentation is very poor.

2012/3/12 shacker <sha...@birdhouse.org>:

> --
> 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/-/G0UkLvyadAgJ.

Matt Schinckel

unread,
Mar 12, 2012, 8:34:32 AM3/12/12
to django...@googlegroups.com
You are mixing up views and forms. The OP was asking about forms, not views.

Personally, I'm starting to hit more and more cases where I would like the form to be able to access the request (and associated data). For instance, being able to limit the queryset of choices for a related field, depending upon the logged in user.

(I have an API framework that uses forms for de/serialisation, called django-repose, but it's not fully ready for human consumption. I'm still thinking about the best way to handle this particular issue, for instance).

Matt.

Tom Evans

unread,
Mar 12, 2012, 8:40:06 AM3/12/12
to django...@googlegroups.com
On Mon, Mar 12, 2012 at 12:34 PM, Matt Schinckel <ma...@schinckel.net> wrote:
> You are mixing up views and forms. The OP was asking about forms, not views.
>
> Personally, I'm starting to hit more and more cases where I would like the
> form to be able to access the request (and associated data). For instance,
> being able to limit the queryset of choices for a related field, depending
> upon the logged in user.
>
> (I have an API framework that uses forms for de/serialisation, called
> django-repose, but it's not fully ready for human consumption. I'm still
> thinking about the best way to handle this particular issue, for instance).
>
> Matt.
>

If your form requires access to the request object, or to the
currently logged in user, it should simply take that object as an
additional required argument to the form constructor. There should be
no need for any magic here.

Cheers

Tom

Reply all
Reply to author
Forward
0 new messages