Skip to content

Django - 页面重定向

在 Web 应用程序中,将用户从一个页面重定向到另一个页面是一个常见需求。例如,用户成功登录后,通常会将他们重定向到仪表板。或者,提交表单后,可能会将他们重定向到成功页面。Django 提供了便捷的方式来处理重定向。

Django 中用于重定向的主要工具是位于 django.shortcuts 中的 redirect() 快捷函数。

redirect() 可以接受几种不同类型的参数:

  • 模型实例: Django 将调用模型的 get_absolute_url() 方法。
  • 视图名称: Django 将使用 reverse() 来查找与该视图名称对应的 URL。传递给 redirect() 的额外参数或关键字参数将用于反向解析 URL。
  • 绝对或相对 URL 路径: 一个字符串,例如 '/some/path/' 或 'https://example.com/'。

我们来看一些例子。假设我们有以下视图和 URL 模式:

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):
# 这个视图已弃用,重定向到新视图
# 使用视图名称和参数进行重定向
return redirect('articles_by_month_archive', year=year, month=month)
def external_redirect_view(request):
# 重定向到外部 URL
return redirect("https://www.djangoproject.com")
def article_detail_view(request, slug):
# 用于显示单个文章的视图
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'), # 重定向的目标
path('external/', views.external_redirect_view, name='external_link'),
path('article/<slug:slug>/', views.article_detail_view, name='article_detail'),
]

在 old_articles_view 中,我们重定向到名为 articles_by_month_archive 的 URL,并传递 year 和 month 参数。Django 在幕后使用 reverse() 来构建正确的 URL (/archive/YYYY/MM/)。

在 external_redirect_view 中,我们直接重定向到一个绝对 URL 字符串。

默认情况下,redirect() 会发出一个临时(HTTP 302 Found)重定向。这会告诉浏览器(和搜索引擎)资源暂时位于新位置,但原始 URL 仍应用于未来的请求。

如果资源已永久移动,则应发出永久(HTTP 301 Moved Permanently)重定向。这对于 SEO(搜索引擎优化)很重要,因为它会告诉搜索引擎使用新 URL 更新其索引。可以通过将 permanent=True 传递给 redirect() 函数来实现:

myapp/views.py
def permanently_moved_view(request):
# 此资源已永久移动到主页
return redirect('home', permanent=True)

虽然 redirect() 在给定视图名称时会在内部处理 URL 反向解析,但有时您只需要 URL 字符串本身,可能用于嵌入模板内容或在 API 响应中使用。为此,您可以使用 django.urls 中的 reverse() 函数。

reverse() 接受视图名称(或 URL 模式名称)以及用于 URL 参数的可选 args(一个元组)或 kwargs(一个字典)。

myapp/views.py
from django.urls import reverse
from django.http import JsonResponse
def api_get_profile_url(request, username):
try:
# 为用户个人资料页生成 URL
profile_url = reverse('user_profile', kwargs={'username': username})
return JsonResponse({'username': username, 'profile_url': profile_url})
except NoReverseMatch:
# 处理 URL 名称或参数不正确的情况
return JsonResponse({'error': 'Could not generate profile URL'}, status=400)

强烈建议使用命名的 URL 模式(path() 或 re_path() 中的 name='...' 参数)。这使您的代码更易于维护,因为您可以更改 urls.py 中实际的 URL 路径,而无需更新代码中其他地方对它们的引用——您只需继续引用名称。

考虑一个需要根据条件进行重定向的场景:

myapp/views.py
def conditional_redirect_view(request):
user = request.user
if user.is_authenticated:
# 将已登录用户重定向到其个人资料页
return redirect('user_profile', username=user.username)
else:
# 将匿名用户重定向到登录页
# 假设 'login' 是您登录 URL 模式的名称
login_url = reverse('login')
return redirect(login_url)

延伸阅读: