HttpResponseRedirect and reverse

54 views
Skip to first unread message

Donn

unread,
Jul 30, 2008, 4:03:33 PM7/30/08
to django-users
Okay, I've got my test app up and limping. I am trying my best not to
hard-code urls and such. One place has my head a little sore; it's in the
view for handling a form.

I did have this (after processing the form):
HttpResponseRedirect('/comic/%s' % os.path.basename(toon.paf))

And I replaced it with:
HttpResponseRedirect(reverse(index,args=[toon.slug]))

The second is better, but I don't know if I get it really.
First off, the form is posting back to the view that drew it. Why can't one
say: HttpResponseRedirect(self,**kwargs)?

Then, the view method is def index(request,showtoon), why can't I refer to the
showtoon variable name? Reverse seems to demand one use 'args'. What of there
were more than one keyword (matched from the urls.py line) - they'd all have
to go in the correct argument order.

Lastly, on the decoupling thing again, if I end up using (sometime)
HttpResposeRedirect(reverse(project.app.view)) does that not tie the view to
the app to the project?

Just wondrin' if there's another way, or what I'm misunderstanding.

\d

Marty Alchin

unread,
Jul 30, 2008, 4:13:01 PM7/30/08
to django...@googlegroups.com
On Wed, Jul 30, 2008 at 4:03 PM, Donn <donn....@gmail.com> wrote:
> Then, the view method is def index(request,showtoon), why can't I refer to the
> showtoon variable name? Reverse seems to demand one use 'args'. What of there
> were more than one keyword (matched from the urls.py line) - they'd all have
> to go in the correct argument order.

Actually, reverse() also accepts a kwargs argument, as documented,[1]
so you can use keyword arguments if that's what your URLpattern uses.
That's the real trick, though. If your URL pattern uses named capture
groups - something like (?P<showtoon>[-\w]+) - you should be using
kwargs. If, on the other hand, you're using anonymous capture groups -
more like ([-\w]+) - then you'll need to use args instead.

-Gul

[1] http://www.djangoproject.com/documentation/url_dispatch/#reverse

Malcolm Tredinnick

unread,
Jul 30, 2008, 4:36:26 PM7/30/08
to django...@googlegroups.com

On Wed, 2008-07-30 at 22:03 +0200, Donn wrote:
> Okay, I've got my test app up and limping. I am trying my best not to
> hard-code urls and such. One place has my head a little sore; it's in the
> view for handling a form.
>
> I did have this (after processing the form):
> HttpResponseRedirect('/comic/%s' % os.path.basename(toon.paf))
>
> And I replaced it with:
> HttpResponseRedirect(reverse(index,args=[toon.slug]))
>
> The second is better, but I don't know if I get it really.
> First off, the form is posting back to the view that drew it. Why can't one
> say: HttpResponseRedirect(self,**kwargs)?

Forms aren't tied to the request/response path. You have access to the
request in the view because it is passed in to all views, but the
coupling between request/response and Forms is almost non-existent
(intentionally), so the form cannot know how it got there. Secondly, not
all forms post back to the view that drew them (in fact, you usually use
the redirect to get *away* from the form submission URL) and you don't
always want to go back to the same place every time the form is
submitted. So this shortcut would have very limited use.


>
> Then, the view method is def index(request,showtoon), why can't I refer to the
> showtoon variable name? Reverse seems to demand one use 'args'. What of there
> were more than one keyword (matched from the urls.py line) - they'd all have
> to go in the correct argument order.
>
> Lastly, on the decoupling thing again, if I end up using (sometime)
> HttpResposeRedirect(reverse(project.app.view)) does that not tie the view to
> the app to the project?

Yes, but you don't have to use that way of referencing things. The
safest way to do this (in terms of "it will always work not matter how
you import things, etc") is to use the url(...) form for url patterns
and use the fourth ("name") parameter to give the pattern a unique name.

Regards,
Malcolm


Donn

unread,
Jul 30, 2008, 4:47:43 PM7/30/08
to django...@googlegroups.com
On Wednesday, 30 July 2008 22:13:01 Marty Alchin wrote:
> Actually, reverse() also accepts a kwargs argument, as documented,[1]
I guess that my use would then be:
reverse(func,kwargs={"showtoon":blah,"something":else})
Because, this one gave me an error:
reverse(func,showtoon=blah,something=else)
Or perhaps it's:
reverse(func,args=None,showtoon=blah,....)

<puzzled>

>(?P<showtoon>[-\w]+) - you should be using
> kwargs.

Okay, and thanks BTW.

\d

Donn

unread,
Jul 30, 2008, 4:55:48 PM7/30/08
to django...@googlegroups.com
On Wednesday, 30 July 2008 22:36:26 Malcolm Tredinnick wrote:
> On Wed, 2008-07-30 at 22:03 +0200, Donn wrote:
> > First off, the form is posting back to the view that drew it. Why can't
> > one say: HttpResponseRedirect(self,**kwargs)?
>
> Forms aren't tied to the request/response path. ... so the form cannot know
how it got there.
Ah, I see -- my mistake, the view is not a class, it's a def. I was
thinking 'self' as in 'me, myself, this view'

Still, there is a path on the django side from a agent-request -> urls -> view
such that there could be a simple way to refer to 'this view'. But perhaps
reverse and unique pattern names *is* that way. Something like
HttpResponseRedirect(".",blah,foo)

> not all forms post back to the view that drew them (in fact, you usually use
> the redirect to get *away* from the form submission URL)

Yes, my use-case is a comment-on-a-cartoon kind of blogish thing. I just
wanted the comment to append to the list on the same page.

> > Lastly, on the decoupling thing again, if I end up using (sometime)

> use the url(...) form for url patterns and use the fourth ("name") parameter
to give the pattern a unique name.

Right, gotcha. Thanks.

\d

Malcolm Tredinnick

unread,
Jul 30, 2008, 4:59:47 PM7/30/08
to django...@googlegroups.com

On Wed, 2008-07-30 at 22:47 +0200, Donn wrote:
> On Wednesday, 30 July 2008 22:13:01 Marty Alchin wrote:
> > Actually, reverse() also accepts a kwargs argument, as documented,[1]
> I guess that my use would then be:
> reverse(func,kwargs={"showtoon":blah,"something":else})
> Because, this one gave me an error:
> reverse(func,showtoon=blah,something=else)
> Or perhaps it's:
> reverse(func,args=None,showtoon=blah,....)

At some point, you should probably just cave in and look at the function
instead of guessing. You can see where it's imported from. :-)

The signature is:

def reverse(viewname, urlconf=None, args=None, kwargs=None, prefix=None): ...

So you can call it as reverse('foo', args=(1, 2, 3)) or reverse('foo',
kwargs={'fred': 1, 'barney': 2}). It's a little fiddly to write a
function like this to just take arbitrary keyword args, because we need
some of the names ("urlconf", "prefix") for our own use and they could
legimitately appear in a URL pattern. So you pass in a dictionary of
kwargs.

Regards,
Malcolm


Donn

unread,
Jul 30, 2008, 5:13:41 PM7/30/08
to django...@googlegroups.com
On Wednesday, 30 July 2008 22:59:47 Malcolm Tredinnick wrote:
> At some point, you should probably just cave in and look at the function
> instead of guessing. You can see where it's imported from. :-)
Good point, I dunno .. I am scared of the source sometimes -- have a hard
enough time with my own code :) Thanks for the help.

\d

bobhaugen

unread,
Jul 31, 2008, 4:43:21 AM7/31/08
to Django users
Maybe I'm missing something obvious again, but why is it called
'reverse'?

Donn

unread,
Jul 31, 2008, 5:33:15 AM7/31/08
to django...@googlegroups.com
On Thursday, 31 July 2008 10:43:21 bobhaugen wrote:
> Maybe I'm missing something obvious again, but why is it called
> 'reverse'?
Hey! At last a question I can answer :)
1. When your view runs it comes from the pattern in urls.py
2. If you want to get from the view back to one of the patterns without
hard-coding something like 'mysite/blah' in your view response redirect, then
you need a way to 'reverse' lookup the pattern.

So, reverse(someViewFunctionName,kwargs={"arg1":val,...}) will find the line
(r'.....',someViewFunctionName,{"arg1":val...}) in urls.py and call that.

Yeep. Reading that I dunno if it helps after all. :)

\d
--
Hofstadter's Law: It always takes longer than you expect, even when you take
into account Hofstadter's Law.

Fonty Python and other dev news at:
http://otherwiseingle.blogspot.com/

Marty Alchin

unread,
Jul 31, 2008, 12:36:59 PM7/31/08
to django...@googlegroups.com
On Thu, Jul 31, 2008 at 4:43 AM, bobhaugen <bob.h...@gmail.com> wrote:
> Maybe I'm missing something obvious again, but why is it called
> 'reverse'?

It's all about URLs and views relating to each other in two
directions. The "forward" case is when a URL gets mapped to a
view+arguments. The "reverse" case is when a view+arguments is mapped
to a URL.

-Gul

Reply all
Reply to author
Forward
0 new messages