19

I'm currently using Django's redirect() method to construct URLs to redirect to. I don't want to hardcode the URL so I've been doing it like this:

return redirect('main.views.home', home_slug=slug)

Which takes me to something like:

/home/test-123/

But I'm adding some client-side tracking for specific URLs so I wanted to use anchors on the end to identify things like first-time user visits like this:

/home/test-123/#first

Short of hardcoding the above URL in the redirect() method, is there a more elegant alternative to append the anchor to the end of my constructed URLs?

Thanks, G

GivP
  • 2,634
  • 6
  • 32
  • 34

3 Answers3

37

redirect() accepts URL, you could use reverse() to get one and appending hash part:

from django.core.urlresolvers import reverse

return redirect(reverse('main.views.home', kwargs={'home_slug':slug}) + '#first')
# or string formatting
return redirect('{}#first'.format(reverse('main.views.home', kwargs={'home_slug':slug})))

Also, there is a shortcut django.shortcuts.resolve_url which works like:

'{}#first'.format(resolve_url('main.views.home', home_slug=slug))

EDIT for Django 2.0, use: from django.urls import reverse

Flux
  • 9,805
  • 5
  • 46
  • 92
okm
  • 23,575
  • 5
  • 83
  • 90
  • 3
    I was going to post that, but you were faster ;) The only difference is that I would probably put some documentation links, use string formatting instead of concatenation and separate these two lines more to stress the import should happen at the beginning of the file. Anyway, +1 – Tadeck Jun 23 '12 at 04:35
9

[Only working up until Django 1.8, not functional in Django 1.9+, see comments!]

You can add an anchor into the regular expression in urls.py. Here is an example from a sample forum app which will jump to the desired post in a thread.

views.py

return redirect(post_list, 
    slug=post.thread.slug, 
    page=1, 
    anchor='post_{0}'.format(post.id)
)

urls.py

url(r'^thread/(?P<slug>[-\w]+)/(?P<page>[0-9]+)/#(?P<anchor>[-_\w]+)$', post_list, name='forum_view_thread'),
url(r'^thread/(?P<slug>[-\w]+)/(?P<page>[0-9]+)/$', post_list, name='forum_view_thread'),
url(r'^thread/(?P<slug>[-\w]+)/$', post_list, name='forum_view_thread'),
Henrik Heimbuerger
  • 9,924
  • 6
  • 56
  • 69
scum
  • 3,202
  • 1
  • 29
  • 27
  • 2
    That's really elegant, so much better than the accepted/upvoted hack, thanks for sharing! – Henrik Heimbuerger Apr 28 '15 at 21:43
  • 2
    It looks like in recent Django 1.9 `#` is going to be escaped as `%23`, so you won't get the expected effect if you use `reverse` function. Quick-and-dirty fix is to add `.replace('%23', '#')`. – Sapphire64 Jan 10 '16 at 10:00
0

just use:

url(r'^app/#/welcome/$', SomeView.as_view(), name='welcome'),

from django.utils.encoding import uri_to_iri
uri_to_iri(urlresolvers.reverse('welcome'))
Googol
  • 2,815
  • 2
  • 22
  • 13