Skip to content

Django - Page Redirection

In web applications, redirecting users from one page to another is a common requirement. For instance, after a user successfully logs in, you typically redirect them to their dashboard. Or, after submitting a form, you might redirect them to a success page. Django provides convenient ways to handle redirection.

The primary tool for redirection in Django is the redirect() shortcut function found in django.shortcuts.

redirect() can accept several types of arguments:

  • A model instance: Django will call the model’s get_absolute_url() method.
  • A view name: Django will use reverse() to find the URL corresponding to that view name. Additional arguments or keyword arguments passed to redirect() will be used to reverse the URL.
  • An absolute or relative URL path: A string like '/some/path/' or 'https://example.com/'.

Let’s look at some examples. Assume we have the following views and URL patterns:

myapp/views.py
from django.http import HttpResponse
from django.shortcuts import redirect, reverse
import datetime
def homepage_view(request):
return HttpResponse("Welcome to the homepage!")
def profile_view(request, username):
return HttpResponse(f"Profile page for user: {username}")
def old_articles_view(request, year, month):
# This view is deprecated, redirect to the new one
# Redirect using a view name and parameters
return redirect('articles_by_month_archive', year=year, month=month)
def external_redirect_view(request):
# Redirect to an external URL
return redirect("https://www.djangoproject.com")
def article_detail_view(request, slug):
# A view for displaying a single article
return HttpResponse(f"Displaying article with slug: {slug}")
# myapp/urls.py
from django.urls import path, re_path
from . import views
urlpatterns = [
path('', views.homepage_view, name='home'),
path('users/<str:username>/', views.profile_view, name='user_profile'),
re_path(r'^articles/(?P<year>\d{4})/(?P<month>\d{2})/$', views.old_articles_view, name='old_articles'),
re_path(r'^archive/(?P<year>\d{4})/(?P<month>\d{2})/$', views.profile_view, name='articles_by_month_archive'), # Target for redirect
path('external/', views.external_redirect_view, name='external_link'),
path('article/<slug:slug>/', views.article_detail_view, name='article_detail'),
]

In old_articles_view, we redirect to the URL named articles_by_month_archive, passing the year and month parameters. Django uses reverse() behind the scenes to construct the correct URL (/archive/YYYY/MM/).

In external_redirect_view, we redirect directly to an absolute URL string.

By default, redirect() issues a temporary (HTTP 302 Found) redirect. This tells the browser (and search engines) that the resource is temporarily at the new location, but the original URL should still be used for future requests.

If the resource has moved permanently, you should issue a permanent (HTTP 301 Moved Permanently) redirect. This is important for SEO, as it tells search engines to update their index with the new URL. You can do this by passing permanent=True to the redirect() function:

myapp/views.py
def permanently_moved_view(request):
# This resource has moved permanently to the homepage
return redirect('home', permanent=True)

While redirect() handles URL reversing internally when given a view name, sometimes you just need the URL string itself, perhaps to embed in template content or use in an API response. For this, you use the reverse() function from django.urls.

reverse() takes the view name (or URL pattern name) and optional args (a tuple) or kwargs (a dictionary) for URL parameters.

myapp/views.py
from django.urls import reverse
from django.http import JsonResponse
def api_get_profile_url(request, username):
try:
# Generate the URL for the user's profile page
profile_url = reverse('user_profile', kwargs={'username': username})
return JsonResponse({'username': username, 'profile_url': profile_url})
except NoReverseMatch:
# Handle cases where the URL name or parameters are incorrect
return JsonResponse({'error': 'Could not generate profile URL'}, status=400)

Using named URL patterns (the name='...' argument in path() or re_path()) is highly recommended. It makes your code more maintainable, as you can change the actual URL paths in urls.py without having to update references to them elsewhere in your code – you just keep referencing the name.

Consider a scenario where you need to redirect based on a condition:

myapp/views.py
def conditional_redirect_view(request):
user = request.user
if user.is_authenticated:
# Redirect logged-in users to their profile
return redirect('user_profile', username=user.username)
else:
# Redirect anonymous users to the login page
# Assume 'login' is the name of your login URL pattern
login_url = reverse('login')
return redirect(login_url)

Further Reading: