Django URL重定向的3種方法詳解(轉載)

最近收到很多讀者的鼓勵,非常開心,這給了我更多將公衆號持續更新下去的動力。今天還收到微信公衆號開通以來的第一份讚賞,在這裏要特別感謝橘子同學。如果你學習的是Python Web開發和Django,本公衆號絕對不會讓你失望,我會爭取所有文章做到清晰易懂,原創免費。如果你是老鳥,本公衆號的內容也可以作爲系統性的參考資料。

 

利用django開發web應用, 我們經常需要進行URL重定向,有時候還需要給URL傳遞額外的參數。比如用戶添加文章完成後需要轉到文章列表或某篇文章詳情。因此熟練掌握HttpResponseDirect, redirect和reverse這三種方法對於Django Web開發是至關重要。今天小編我就帶你看下Django URL重定向的HttpResponseDirect, redirect和reverse方法的詳細用法。

 

 

 

HttpResponseDirect方法

HttpResponseRedirect是django首選的URL重定向方法,在django.http模塊裏。該方法的第一個參數是必要的,是用來重定向的URL地址。這個URL可以是完整的鏈接(比如’http://www.baidu.com‘),也可以是一個不包含域名的靜態鏈接(例如‘/index/’)。

 

我們下面以新聞博客(blog)爲例來看看如何使用HttpResponseDirect方法。假如我們有如下3個urls, 一個展示文章,一個添加文章,一個展示文章詳情。我們需要使用該方法在視圖中實現兩種URL重定向:

  • 轉向不含參數的URL: 用戶添加文章完成後轉向文章列表(/index/); 或
  • 轉向包含參數的URL: 用戶添加文章完成後轉向文章詳情(/article/2/new-day/)
from django.urls import path, re_path
from . import views

# namespace
app_name = 'blog'
urlpatterns = [
    # 展示所有文章
    path('/index/', views.ArticleListView.as_view(), name='article_list'),
    # 展示文章詳情
    re_path(r'^article/(?P<pk>\d+)/(?P<slug1>[-\w]+)/$',
            views.ArticleDetailView.as_view(), name='article_detail'),
    # 添加文章
    re_path(r'^article/create/$',
            views.ArticleCreateView.as_view(), name='article_create'),
]

 

1. 在視圖views.py中利用HttpResponse重新定向至不含參數的URL

from .models import Article, 
from django.http import HttpResponseRedirect
from django.shortcuts import render
from .forms import ArticleForm

def article_create(request):
    if request.method == 'POST':
        form = ArticleForm(request.POST)
        if form.is_valid():
            form.save()  
            return HttpResponseRedirect("/index/")
    else:
        form = ArticleForm()
    return render(request, 'blog/article_create_form.html', {'form': form})

如果/index/頁面有分頁功能, 你還可以通過使用HttpResponseRedirect('/index/?page=2')直接獲取第2頁的文章列表。

 

HttpReponseDirect只支持hard coded urls(硬編碼鏈接), 不能直接使用命名的URL,如使用HttpResponseDirect('blog:article_list‘)是錯誤的。在使用URL命名時,我們需要先通過URL反向解析方法reverse先對命名URL(article_list)進行解析,然後再使用HttpReponseRedirect定向(如下面的代碼)。背後的邏輯是reverse('blog:article_list')='/index/'。

......
from django.http import HttpResponseRedirect
from django.urls import reverse
.....

def article_create(request):
    if request.method == 'POST':
        form = ArticleForm(request.POST)
        if form.is_valid():
            form.save()
            return HttpResponseRedirect(reverse('blog:article_list'))
   ....

 

2. 在視圖views.py中利用HttpResponseDirect重新定向至包含參數的URL

對於包含參數的URL(/article/2/new-day/),使用HttpResponseDirect定向前一般需要先使用reverse方法對命名的URL(如'article_detail')進行解析,同時傳遞參數(如id, slug等)。

from .models import Article
from django.http import HttpResponseRedirect
from django.urls import reverse
from django.shortcuts import render
from .forms import ArticleForm

def article_create(request):
    if request.method == 'POST':
        form = ArticleForm(request.POST)
        if form.is_valid():
            article = form.save()
            return HttpResponseRedirect(reverse('blog:article_detail', args=[str(article.pk), article.slug]))
    else:
        form = ArticleForm()
    return render(request, 'blog/article_create_form.html', {'form': form})

 

其中最重要的一行代碼如下所示。大家可以仔細看下參數是如何傳遞到url的。

reverse('blog:article_detail', args=[str(article.pk), article.slug]

 

redirect方法

redirect是URL重新定向的便捷方法,在django.shortcuts模塊裏。HttpResponseRedirect能支持的URL重定向,redirect都支持。比如下面3種重定向是redirect的常規用法。

from django.shortcuts import redirect
from django.urls import reverse

# 案例1
def my_view(request):
    ...
    return redirect('/index/')

# 案例2
def my_view(request):
    ...
    return redirect('https://www.baidu.com/')

# 案例3
def my_view(request):
    ...
    return redirect(reverse('blog:article_list'))

redirect真正NB的地方在於,它不僅能根據URL重定向,還可以根據對象Object重定向和根據視圖view重定向,根據視圖重定向的時候還可以傳遞額外的參數。

 

1. 根據對象Object重定向

使用該方法的前提是模型裏已經定義了get_asbolute_url方法,使用redirect會自動調用get_absolute_url方法。

from django.shortcuts import redirect

def my_view(request):
    ...
    obj = MyModel.objects.get(...)
    return redirect(obj)

 

2. 根據視圖view重定向

使用該方法的前提已對URL進行了命名,且對應了相應的視圖。下面案例中redirect會先根據視圖函數的名字查找對應url,在傳遞額外參數。後臺工作還是由reverse方法來完成的。

def my_view(request):
    ...
    return redirect('some-view-name', foo='bar')

 

reverse方法

reverse方法的作用是對已命名的URL進行反向解析,還傳遞相應的參數(args或帶key的參數kargs)。該方法位於django.urls模塊。reverse方法一般有2種應用場景:

  • 在模型中自定義get_absolute_url時使用,傳遞參數
  • 在視圖中對命名URL進行解析,傳遞參數,再使用HttpResponseDirect和redict進行重定向

 

1. 模型中自定義get_absolute_url,並傳遞參數args

def get_absolute_url(self):
    return reverse('blog:article_detail', args=[str(self.pk), self.slug])

 

2. 在視圖中配合URL重定向使用,並傳遞kargs

from django.urls import reverse
from django.shortcuts import redirect

def my_view(request):
    ...
    return redirect(reverse('admin:app_list', kwargs={'app_label': 'auth'}))

 

還有一點容易被人們忽略的是reverse方法不僅能對命名的urls進行反向解析,還可以對視圖函數進行反向解析,找到需要重新定向的url, 如下面代碼所示。當然但這個方法我們並不推薦使用。與此功能相反的是resolve方法,該方法可以根據url找到對應視圖函數。

from django.urls import reverse
from blog import views
reverse(views.index)

 

小結

HttpResponseDirect, redirect和reverse三個方法都非常常用,在使用它們前忘了import進來哦。注意它們在不同的模塊。

  • HttpResponseDirect - django.http
  • redirect - django.shortcuts
  • reverse - django.urls

原文轉自知乎:https://zhuanlan.zhihu.com/p/41547331

感謝原作者~

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章