In Django, how can I do a simple redirect directly from urls.py? Naturally I am a well organized guy, favoring the DRY principle, so I would like to get the target based on it's named url pattern, rather than hard coding the url.
7 Answers
You can use RedirectView.
If you are on Django 1.4 or 1.5, you can do this:
from django.core.urlresolvers import reverse_lazy
from django.views.generic import RedirectView
urlpatterns = patterns('',
url(r'^some-page/$', RedirectView.as_view(url=reverse_lazy('my_named_pattern'), permanent=False)),
...
If you are on Django 1.6 or above, you can do this:
from django.views.generic import RedirectView
urlpatterns = patterns('',
url(r'^some-page/$', RedirectView.as_view(pattern_name='my_named_pattern', permanent=False)),
...
In Django 1.9, the default value of permanent has changed from True to False. Because of this, if you don't specify the permanent keyword argument, you may see this warning:
RemovedInDjango19Warning: Default value of 'RedirectView.permanent' will change from True to False in Django 1.9. Set an explicit value to silence this warning.
7 Comments
(r'^.*/$', RedirectView.as_view(url='http://newurl.com')),pattern_name argument to RedirectView executes reverse for you at call time using given pattern name. Other useful parameters include permanent and query_string.This works for me.
from django.views.generic import RedirectView
urlpatterns = patterns('',
url(r'^some-page/$', RedirectView.as_view(url='/')),
...
In above example '/' means it will redirect to index page,
where you can add any url patterns also.
1 Comment
RedirectView has permanent=True as default in older versions of Django, and permanent=False as default in Django versions >= 1.9.for django v2+
from django.contrib import admin
from django.shortcuts import redirect
from django.urls import path, include
urlpatterns = [
# this example uses named URL 'hola-home' from app named hola
# for more redirect's usage options: https://docs.djangoproject.com/en/2.1/topics/http/shortcuts/
path('', lambda request: redirect('hola/', permanent=False)),
path('hola/', include("hola.urls")),
path('admin/', admin.site.urls),
]
1 Comment
permanent=False is the default. For more details please read: docs.djangoproject.com/en/2.1/topics/http/shortcuts/#redirect developer.mozilla.org/en-US/docs/Web/HTTP/…This way is supported in older versions of django if you cannot support RedirectView
In view.py
def url_redirect(request):
return HttpResponseRedirect("/new_url/")
In the url.py
url(r'^old_url/$', "website.views.url_redirect", name="url-redirect"),
You can make it permanent by using HttpResponsePermanentRedirect
Comments
You could do straight on the urls.py just doing something like:
url(r'^story/(?P<pk>\d+)/',
lambda request, pk: HttpResponsePermanentRedirect('/new_story/{pk}'.format(pk=pk)))
Just ensure that you have the new URL ready to receive the redirect!! Also, pay attention to the kind of redirect, in the example I'm using Permanent Redirect
Comments
If you need to capture part of the url including slashes and directly reuse that in the redirect, you can use re_path like this:
from django.shortcuts import redirect
from django.urls import re_path
re_path(r"admin/old_module/(.+)$", lambda req, rest: redirect(f"/admin/new_module/{rest}"))
Here rest is a positional argument containing the first capture group (.+). More arguments/capture groups could be added in the same manner. (see re_path)