30

Consider that I have 1 resource and 2 urls (let's say new one and old one) connected to that resourse. So, i want to setup HTTP redirection for one of urls.

In myapp/urls.py I have:

urlpatterns = patterns('',
    url(r'^(?P<param>\d+)/resource$', 
                      'myapp.views.resource', 
                       name='resource-view'
    ),
)

In mycoolapp/urls.py I want to specify:

from django.views.generic.simple import redirect_to
from django.core.urlresolvers import reverse_lazy

urlpatterns = patterns('',
    url(r'^coolresource/(?P<param>\d+)/$', 
                       redirect_to, 
                       {
                          'url': reverse_lazy('resourse-view', 
                                         kwargs={'param': <???>}, 
                                         current_app='myapp'
                                 ),
                       }
   ),
)

The question is how to pass <param> to the reverse_lazy kwargs (so, what to put instead of <???> in the example above)?

gakhov
  • 1,925
  • 4
  • 27
  • 39

6 Answers6

31

I wouldn't do this directly in the urls.py, I'd instead use the class-based RedirectView to calculate the view to redirect to:

from django.views.generic.base import RedirectView
from django.core.urlresolvers import reverse_lazy

class RedirectSomewhere(RedirectView):
    def get_redirect_url(self, param):
        return reverse_lazy('resource-view',
                            kwargs={'param': param},
                            current_app='myapp')

Then, in your urls.py you can do this:

urlpatterns = patterns('',
    url(r'^coolresource/(?P<param>\d+)/$', 
        RedirectSomewhere.as_view()),
)
slurms
  • 748
  • 1
  • 7
  • 15
7

Redirect View is great if you are using a hard coded url, it replaced redirect_to which is now deprecated. I don't think you can use it when redirecting and reversing from urls.py. Here is my solution, x is the response object in this case:

from django.core.urlresolvers import reverse
from django.http import HttpResponseRedirect
urlpatterns = patterns('',
    ....
    url(r'^coolresource/(?P<param>\d+)/$',
                         lambda x, param: HttpResponseRedirect(
                             reverse('myapp.views.resource', args=[param])
                         ),
                         name='resource-view-redirect'),
    ....
)

You can still use the name of the url pattern instead of a hard coded url with this solution. The location_id parameter from the url is passed down to the lambda function.

Olivier Pons
  • 15,363
  • 26
  • 117
  • 213
radtek
  • 34,210
  • 11
  • 144
  • 111
6

As of Django 1.6 you can do this (Documentation):

...
from django.views.generic.base import RedirectView

urlpatterns = patterns('',
    url(r'^coolresource/(?P<param>\d+)/$', 
         RedirectView.as_view(pattern_name='resource-view'),
    ),
) 
Pykler
  • 14,565
  • 9
  • 41
  • 50
3

One of the possible solutions of the general problem is to use hard-coded url pattern instead of reverse_lazy (documentation)

url(r'^coolresource/(?P<param>\d+)/$', 
                       redirect_to, 
                       {'url': '/%(param)s/resource'}
),

But, I don't like it so much, since it makes me harder after to do possible changes in urls.

gakhov
  • 1,925
  • 4
  • 27
  • 39
1

You can't know or get what the value is until the view is called, so calculate url inside it.

Ignacio Vazquez-Abrams
  • 776,304
  • 153
  • 1,341
  • 1,358
0

Django's regex matching method for urls allows one to define and assign variables:

(?P<variable_name>...) defines variable_name depending on the uri being called; so what you need to put is: param instead of <???>

Umur Kontacı
  • 35,403
  • 8
  • 73
  • 96