10

I'd like to redirect url pattern with variables from urls.py.

I refer other stackoverflow solution, but I don't know when url having a variable like following code.

from django.conf.urls import patterns, url
from django.views.generic import RedirectView


urlpatterns = patterns(
    url(
        r'^permalink/(?P<id>\d+)/foo/$',
        RedirectView.as_view(url='/permalink/(?P<id>\d+)/')
    ),
)

With this code, django will redirect /permalink/1/foo/ to /permalink/(?P<id>\d+)/, not the /permalink/1/.

Is there any solution without using views.py?

Of course I know solution using controller, but I wonder is there any simpler solution with using url pattern.

Community
  • 1
  • 1
Chemical Programmer
  • 4,352
  • 4
  • 37
  • 51

1 Answers1

15

Passing url='/permalink/(?P<id>\d+)/' to RedirectView will not work, because the view does not substitute the named arguments in the url.

However, RedirectView lets you provide the pattern_name instead of the url to redirect to. The url is reversed using the same args and kwargs that were passed for the original view.

This will work in your case, because both url patterns have one named argument, id.

urlpatterns = [
    url(r'^permalink/(?P<id>\d+)/foo/$',
        RedirectView.as_view(pattern_name="target_view"),
        name="original_view"),
    url(r'^permalink/(?P<id>\d+)/$', views.permalink, name="target_view"),
]

If the target url pattern uses other arguments, then you can't use url or pattern_name. Instead, you can subclass RedirectView and override get_redirect_url.

from django.core.urlresolvers import reverse
from django.views.generic import RedirectView

class QuerystringRedirect(RedirectView):
    """
    Used to redirect to remove GET parameters from url

    e.g. /permalink/?id=10 to /permalink/10/   
    """

    def get_redirect_url(self):
        if 'id' in self.request.GET:
            return reverse('target_view', args=(self.request.GET['id'],))
        else:
            raise Http404()

It would be good practice to put QuerystringRedirect in your views module. You would then add the view to your url patterns with something like:

urlpatterns = [
    url(r'^permalink/$', views.QuerystringRedirect.as_view(), name="original_view"),
    url(r'^permalink/(?P<id>\d+)/$', views.permalink, name="target_view"),
]
Alasdair
  • 298,606
  • 55
  • 578
  • 516