天天看點

Django視圖層Django視圖層

Django視圖層

  • Django視圖層
    • 概述
    • 簡單的視圖執行個體
    • 傳回錯誤頁面
      • HTTP 404異常
    • Djangoy請求和響應對象
      • HttpRequest對象
        • HttpRequest主要屬性
        • HttpRequest主要方法
      • HttpResponse 對象
        • HttpResponse()
        • render()
        • redirect()
      • get_object_or_404()
      • get_list_or_404()

概述

Django的視圖層,通俗的說使用者請求從路由層urls.py處理後就來到了這一層,往下就是視情況走model層(資料庫)或直接傳回templates模闆中的html頁面,又或者直接用函數方法快捷處理了,可以說是一個很重要也很貼近程式設計代碼的一層。

基本在此子產品我們所寫的代碼方式和python中一樣,主要以def函數為主。

也是以,雖然簡稱為視圖,習慣稱為視圖函數,它的本質上就是一個寫滿密密麻麻的函數的python子產品。

此外,它主要做的是接收路由分發過來的web請求并且傳回web響應。

響應的内容一般最終會是一個經過資料處理的HTML網頁;

也包括了重定向、404錯誤,XML文檔或圖像等任何東西。

但是,無論視圖本身是個什麼處理邏輯,最好都傳回某種響應。

比喻

是不是感覺有點像在飯店裡看着菜單點單,服務員上各種菜式給你一樣。

沒錯,這裡我們到店點單,菜單就相當于接受我們最初請求的路由層,服務員送到後廚就相當于是送進了視圖層,後廚根據這些請求(下單點的菜式)對應傳回響應(按菜單做好菜)并讓服務員将結果上到你桌上。(使用者接收到響應)

通常我們約定将視圖放置在項目或應用程式目錄中,且命名為

views.py

檔案。

簡單的視圖執行個體

  • 寫一個傳回目前日期和時間的HTML文檔視圖:

urls.py

檔案中指定通路位址部分:

urlpatterns = [
     path('time/', views.current_datatime,)
]
           

views.py

檔案中添加:

from django.http import HttpResponse
import datetime

def current_datetime(request):
    now = datetime.datetime.now()
    html = "<html><body><h1>目前時間為:%s <h1></body></html>" % now
    return HttpResponse(html)
           

上述代碼做了些什麼呢?

  • 它首先,從django.http子產品導入了HttpResponse類,以及Python的datetime庫。
  • 接着,定義了一個名字為自定義的

    current_datetime

    的視圖函數。
  • 最後,它傳回了一個HttpResponse對象,其中包含生成的顯示目前時間的HTML頁面。

注:

* 每個視圖函數都接收一個HttpRequest對象作為第一位置參數,一般取名為request,你可以取别的名字,但這不符合約定俗成,最好不要那麼做。情形就類似學習面向對象的時候,一個類的方法通常會接收一個預設叫做self的第一位置參數一樣。

  • 視圖函數的名稱沒有強制規則,但盡量不要和Python及Django内置的各種名稱重名,并且盡量精确地反映出它的功能。(顧名思義)

最終效果為使用者通路

/time/

頁面顯示如圖:

Django視圖層Django視圖層

傳回錯誤頁面

  • Django中的錯誤頁面一般我們不用,不過做為學習和開發測試階段,玩一下也是可以的。
  • Django中主要使用HttpResponse對象來簡單傳回HTTP錯誤代碼。
    • 因HttpResponse的許多子類對應着一些常用的HTTP狀态碼。

标示一個錯誤,可以直接傳回那些子類中的一個執行個體,而不用普通的HttpResponse也可以。

像下例:

  • urls.py

    檔案代碼相關部分:
urlpatterns = [
     path('test/', views.test_error),
]
           
  • views.py

    檔案代碼相關部分:
from django.http import HttpResponse, HttpResponseNotFound

# Create your views here.

def test_error(request):
    # 測試用,可定義一個foo函數,傳回ture或false的布爾值進行觀測。
    if foo:
        return HttpResponseNotFound('<h1>404 :Page not found </h1>')
    else:
        return HttpResponse('<h1>歡迎光臨</h1>')
           

Django為404錯誤提供了一個特化的子類HttpResponseNotFound。

一些不太常見和常用的狀态碼就沒有這個特殊待遇了。畢竟404太常打交道了。

通路效果如下,可通過控制台看到的确是404狀态。

Django視圖層Django視圖層

類似地,其他一些常用的特定狀态HttpResponse子類如下:

  • HttpResponseRedirect:傳回Status 302,用于URL重定向,需要将重定向的目标位址作為參數傳給該類。
  • HttpResponseNotModified:傳回Status 304,用于訓示浏覽器用其上次請求時的緩存結果作為頁面内容顯示。
  • HttpResponsePermanentRedirect: 傳回Status 301,永久重定向。
  • HttpResponseBadRequest:傳回Status 400,請求内容錯誤。
  • HttpResponseForbidden:傳回Status 403 , 禁止通路錯誤。
  • HttpResponseNotAllowed : 傳回Status 405,用不允許的方法(Get、Post、Head等)通路本頁面。
  • HttpResponseServerError: 傳回Status 500, 伺服器内部錯誤,比如無法處理的異常等。

也可以向HttpResponse的構造器傳遞HTTP狀态碼,來建立你想要的任何狀态碼的傳回類。

例,修改上述例子代碼相關部分:

from django.http import HttpResponse, HttpResponseNotFound

def test_error(request):
    return HttpResponse(status=)
           

如圖,通路效果:

Django視圖層Django視圖層

HTTP 404異常

class django.http.Http404

是一個Django内置的異常類。

可以在你認為需要的地方彈出它,Django會捕獲它,

并且帶上HTTP404錯誤碼傳回你目前app的标準錯誤頁面或者自定義的錯誤頁面。

例,同樣接上述例子修改部分代碼進行測試:

from django.http import Http404
from django.shortcuts import render

def test_error(request):
    # 測試用,正常可定義一個執行體,進行try和except捕獲異常,進行觀測。
    if :
        raise Http404('測試錯誤資訊 by tielemao')
    else:
        return HttpResponse('歡迎')
           

效果如圖:

Django視圖層Django視圖層

上面是我為了友善測試用的簡單代碼,下面有一個例子使用try和except對照:

from django.http import Http404
from django.shortcuts import render
from polls.models import Poll

def detail(request, poll_id):
    try:
        p = Poll.objects.get(pk=poll_id)
    except Poll.DoesNotExist:
        raise Http404("Poll does not exist")
    return render(request, 'polls/detail.html', {'poll': p})
           

為了在Django傳回404時顯示自定義的HTML,

可以建立一個名為404.html的HTML模闆,并将其放置在模闆樹的頂層。

當在

settings.py

檔案中DEBUG設定為False時,此模闆将被自動使用。

當DEBUG為True時,可以向Http404提供消息,

它将顯示在标準的内置404調試模闆中,可以使用這些消息進行調試。

上面例子的效果圖就是DEBUG為True時的。可見自定義的消息。

當然這些調試資訊都隻會在開發測試階段顯示,

正式線上環境時DEBUG必然是為了安全(不能暴露資訊)要設定為False的。

Djangoy請求和響應對象

Django 是圍繞着 Request 與 Response 進行處理,也就是無外乎“求”與“應”。

當請求一個頁面時,Django 把請求的 metadata 資料包裝成一個 HttpRequest 對象,然後 Django 加載合适的 view 方法,把這個 HttpRequest 對象作為第一個參數傳給 view 方法。

任何 view 方法都應該傳回一個 HttpResponse 對象。

Django視圖層Django視圖層

Django在django.shortcuts子產品中,提供了很多快捷友善的類和方法。

下面着重介紹相對很重要,使用頻率很高的一些類和方法。

HttpRequest對象

每當一個使用者請求發送過來,Django将HTTP資料包中的相關内容,打包成為一個HttpRequest對象,并傳遞給每個視圖函數作為第一位置參數,也就是request,供我們調用。

HttpRequest對象中包含了非常多的重要的資訊和資料,應該熟練掌握它。

* 類定義:

class HttpRequest[source]

HttpRequest主要屬性

django将請求封包中的請求行、首部資訊、内容主體封裝成 HttpRequest 類中的屬性。

除了特殊說明的之外,其他均為隻讀。

  • HttpRequest.scheme (協定)
    • 表示請求的協定種類,http或https;
    • 字元串類型。
  • HttpRequest.body (正文主體)
    • 表示原始HTTP請求的正文;
    • 對于處理非HTML形式的資料非常有用,例:圖像(二進制)、XML等;
    • bytes類型。
  • HttpRequest.path (路徑)
    • 表示目前請求頁面的完整路徑(不包括協定名和域名);
    • 常用于判斷執行某操作時,不通過則傳回使用者先前浏覽的頁面;
    • 字元串類型。
  • HttpRequest.path_info (路徑資訊)
    • 在某些Web伺服器配置下,主機名後的URL部分被分成腳本字首部分和路徑資訊部分。
    • path_info

      屬性将始終包含路徑資訊部分,不論使用的Web伺服器是什麼。
    • 使用它代替path可以讓代碼在測試和開發環境中更容易地切換。

      例:如果應用的WSGIScriptAlias設定為

      /minfo

      ,那麼

      HttpRequest.path

      等于

      /music/bands/the_beatles/

      ,而

      HttpRequest.path_info

      /minfo/music/bands/the_beatles/

  • HttpRequest.method (請求方法)
    • 表示請求使用的HTTP方法。
    • 預設為大寫。
    • 常用于處理正常的form表單資料。根據請求的方法不同,在視圖中判斷執行不同的代碼。
    • 字元串類型。
  • HttpRequest.GET (GET請求)
    • 包含HTTP GET的所有參數;
    • 類似于字典的對象;
    • 屬于

      django.http.QueryDict

      對象的執行個體,能調用QueryDict對象的方法。
  • HttpRequest.POST (POST請求)
    • 包含所有HTTP POST請求的參數及表單資料;
    • 類似于字典的對象;
    • 屬于

      django.http.QueryDict

      對象的執行個體,能調用QueryDict對象的方法。
    • 不包含上傳檔案的資料,檔案資訊包含在FILES屬性中;
    • POST請求可以為空且QueryDict執行個體依然會建立,是以,視圖函數中檢查請求使用的是否是POST方法,不應使用

      if request.POST

      而應使用

      if request.method == "POST"

      ;
    • 鍵值對是多個的時候(如checkbox類型的input标簽,select标簽)需使用

      request.POST.getlist("hobby")

      之類。
  • HttpRequest.encoding (編碼方式)
    • 表示送出的資料的編碼方式;
    • 如為None則表示使用

      DEFAULT_CHARSET

      設定;
    • 此屬性為可寫,可以修改它來改變表單資料的編碼,使随後的屬性通路(例GET或POST)将使用新的編碼方式。
  • HttpRequest.COOKIES
    • 包含所有Cookie資訊的字典。
    • 鍵和值都為字元串。
    • 可以以類似字典類型的方式,在cookie中讀寫資料。
    • 注意cookie是不安全的,不要寫入或透露敏感重要資訊。
  • HttpRequest.FILES (檔案上傳)
    • 類似字典的對象;
    • 包含所有上傳的檔案資料;
    • 每個鍵為

      <input type="file" name="" />

      中的name屬性值;
    • 每個值為一個上傳的檔案

      UploadedFile

    • Django中實作檔案上傳,靠的是這個屬性。
    • 如果請求的方法是POST且請求的

      <from>

      中帶有

      enctype="multipart/form-data"

      屬性,那麼FILES将包含上傳的檔案的資料。 否則,FILES将為一個空的類似于字典的對象,屬于被忽略、無用的情形。
  • HttpRequest.META (頭部資訊)
    • 包含所有HTTP頭部資訊的字典。 可用的頭部資訊取決于用戶端和伺服器。

      下面是一些示例:

CONTENT_LENGTH —— 請求正文的長度(以字元串計)。
    CONTENT_TYPE —— 請求正文的MIME類型。
    HTTP_ACCEPT —— 可接收的響應Content-Type。
    HTTP_ACCEPT_ENCODING —— 可接收的響應編碼類型。
    HTTP_ACCEPT_LANGUAGE —— 可接收的響應語言種類。
    HTTP_HOST —— 客服端發送的Host頭部。
    HTTP_REFERER —— Referring頁面。
    HTTP_USER_AGENT —— 用戶端的user-agent字元串。
    QUERY_STRING —— 查詢字元串。
    REMOTE_ADDR —— 用戶端的IP位址。想要擷取用戶端的ip資訊,就在這裡!
    REMOTE_HOST —— 用戶端的主機名。
    REMOTE_USER —— 伺服器認證後的使用者,如果可用。
    REQUEST_METHOD —— 表示請求方法的字元串,例如"GET" 或"POST"。
    SERVER_NAME —— 伺服器的主機名。
    SERVER_PORT —— 伺服器的端口(字元串)。
           

以上隻是比較重要和常用的,還有很多未列出。

從上面可以看到,除CONTENT_LENGTH和CONTENT_TYPE之外,請求中的任何HTTP頭部鍵轉換為META鍵時,都會将所有字母大寫并将連接配接符替換為下劃線最後加上HTTP_字首。是以,一個叫做X-Bender的頭部将轉換成META中的HTTP_X_BENDER鍵。

  • 可自定義的屬性
    • Django不會自動設定下面這些屬性,而是由你自己在應用程式中設定并使用它們。
    • HttpRequest.current_app
      • 表示目前app的名字。
      • url模闆标簽将使用其值作為

        reverse()

        方法的current_app參數。
    • HttpRequest.urlconf
      • 設定目前請求的根URLconf,用于指定不同的url路由進入口,
      • 覆寫settings中的

        ROOT_URLCONF

        設定。
      • 将它的值修改為None,可以恢複使用

        ROOT_URLCONF

        設定。
  • 由中間件設定的屬性
    • Django的contrib應用中包含的一些中間件會在請求上設定屬性。
    • HttpRequest.session (會話)
      • SessionMiddleware中間件:一個可讀寫的,類似字典的對象,表示目前會話。
      • 我們要儲存使用者狀态,回話過程等等,靠的就是這個中間件和這個屬性。
    • HttpRequest.site (站點)
      • CurrentSiteMiddleware中間件:

        get_current_site()

        方法傳回的Site或RequestSite的執行個體,代表目前站點是哪個。
      • Django是支援多站點的,如果你同時上線了幾個站點,就需要為每個站點設定一個站點id。
    • HttpRequest.user (使用者)
      • AuthenticationMiddleware中間件:表示目前登入的使用者的

        AUTH_USER_MODEL

        的執行個體;
      • 這個模型是Django内置的Auth子產品下的User模型。如果使用者目前未登入,則user将被設定為AnonymousUser的執行個體。
      • 可以使用is_authenticated方法判斷目前使用者是否合法使用者,如下所示:
if request.user.is_authenticated:
    ... # Do something for logged-in users.
else:
    ... # Do something for anonymous users.
           

HttpRequest主要方法

  • HttpRequest.get_host()[source]

    • 根據

      HTTP_X_FORWARDED_HOST

      HTTP_HOST

      頭部資訊擷取請求的原始主機。
    • 如果這兩個頭部沒有提供相應的值,則使用

      SERVER_NAME

      SERVER_PORT

    • 例:”127.0.0.1:8080”
    • 注:當主機位于多個代理的後面,

      get_host()

      方法将會失敗。
    • 解決辦法之一是使用中間件重寫代理的頭部,如下面的例子:
from django.utils.deprecation import MiddlewareMixin

class MultipleProxyMiddleware(MiddlewareMixin):
    FORWARDED_FOR_FIELDS = [
        'HTTP_X_FORWARDED_FOR',
        'HTTP_X_FORWARDED_HOST',
        'HTTP_X_FORWARDED_SERVER',
    ]

    def process_request(self, request):
        """
        Rewrites the proxy headers so that only the most
        recent proxy is used.
        """
        for field in self.FORWARDED_FOR_FIELDS:
            if field in request.META:
                if ',' in request.META[field]:
                    parts = request.META[field].split(',')
                    request.META[field] = parts[-].strip()
           
  • HttpRequest.get_port()[source]

    • 使用META中

      HTTP_X_FORWARDED_PORT

      SERVER_PORT

      的資訊傳回請求的始發端口。
  • HttpRequest.get_full_path()[source]

    • 傳回包含完整參數清單的path。例如:

      /music/bands/the_beatles/?print=true

  • HttpRequest.build_absolute_uri(location)[source]

    • 傳回location的絕對URI形式。
    • 如果location沒有提供,則使用

      request.get_full_path()

      的值。
    • 例如:

      "https://example.com/music/bands/the_beatles/?print=true"

    • 注:不鼓勵在同一站點混合部署HTTP和HTTPS,如果需要将使用者重定向到HTTPS,最好使用Web伺服器将所有HTTP流量重定向到HTTPS。
  • HttpRequest.get_signed_cookie(key, default=RAISE_ERROR, salt='', max_age=None)[source]

    • 從已簽名的Cookie中擷取值,如果簽名不合法則傳回django.core.signing.BadSignature。
    • 可選參數salt用來為密碼加鹽,提高安全系數。 max_age參數用于檢查Cookie對應的時間戳是否逾時。

範例:

>>> request.get_signed_cookie('name')
'Tony'
>>> request.get_signed_cookie('name', salt='name-salt')
'Tony' # assuming cookie was set using the same salt
>>> request.get_signed_cookie('non-existing-cookie')
...
KeyError: 'non-existing-cookie'
>>> request.get_signed_cookie('non-existing-cookie', False)
False
>>> request.get_signed_cookie('cookie-that-was-tampered-with')
...
BadSignature: ...
>>> request.get_signed_cookie('name', max_age=)
...
SignatureExpired: Signature age  >  seconds
>>> request.get_signed_cookie('name', False, max_age=)
False
           
  • HttpRequest.is_secure()[source]

    • 如果使用的是Https,則傳回True,表示連接配接是安全的。
  • HttpRequest.is_ajax()[source]

    • 如果請求是通過XMLHttpRequest生成的,則傳回True。
    • 這個方法的作用就是判斷,目前請求是否通過ajax機制發送過來的。
  • 從HttpRequest執行個體讀取檔案資料的方法:
、HttpRequest.read(size=None)[source]
、HttpRequest.readline()[source]
、HttpRequest.readlines()[source]
、HttpRequest.xreadlines()[source]
、HttpRequest.iter()
           
* 可以将HttpRequest執行個體直接傳遞到XML解析器,例如ElementTree:
           
import xml.etree.ElementTree as ET
for element in ET.iterparse(request):
    process(element)
           

HttpResponse 對象

Request 和 Response 對象起到了伺服器與客戶機之間的資訊傳遞作用。

Request 對象用于接收用戶端浏覽器送出的資料,而 Response 對象的功能則是将伺服器端的資料發送到用戶端浏覽器。

與由Django自動建立的HttpRequest 對象相比,

HttpResponse 對象由程式員建立.你建立的每個視圖負責初始化執行個體,

填充并傳回一個 HttpResponse。

每個 View 方法必須傳回一個 HttpResponse 對象。

HttpResponse 類是在django.http子產品中定義的。

主要介紹下面三種方法:

  • HttpResponse()

    傳遞字元串
  • render()

    結合一個給定的模闆和一個給定的上下文字典,并傳回一個渲染後的 HttpResponse 對象。
  • redirect()

    重定向

HttpResponse()

以字元串的形式傳遞給頁面。

一般地,你可以通過給 HttpResponse 的構造函數傳遞字元串表示的頁面内容來構造HttpResponse 對象:

>>> response = HttpResponse("Welcome to tielemao.com.")
>>> response = HttpResponse("Text only, please.", mimetype="text/plain")
           

如果想要增量添加内容, 你可以把response當作filelike對象使用:

response = HttpResponse()
response.write("<p>Welcome to tielemao.com.</p>")
response.write("<p>Here's another paragraph.</p>")
           

也可以給 HttpResponse 傳遞一個 iterator 作為參數,而不用傳遞寫死字元串。

如果你使用這種技術,下面是需要注意的一些事項:

  • iterator 應該傳回字元串。
  • 如果 HttpResponse 使用 iterator 進行初始化,就不能把 HttpResponse 執行個體作為 filelike 對象使用。這樣做将會抛出異常。

最後,再說明一下,HttpResponse 實作了

write()

方法,可以在任何需要 filelike 對象的地方使用 HttpResponse 對象。

render()

  • 文法

    render(request, template_name, context=None, content_type=None, status=None, using=None)[source]

  • 用處:結合一個給定的模闆和一個給定的上下文字典,傳回一個渲染後的HttpResponse對象。
  • 必要參數:
    • request:視圖函數處理的目前請求,封裝了請求頭的所有資料,其實就是視圖參數request。
    • template_name:要使用的模闆的完整名稱或者模闆名稱的清單。
      • 如果是一個清單,将使用其中能夠查找到的第一個模闆。
  • 可選參數:
    • context:添加到模闆上下文的一個資料字典。預設是一個空字典。
      • 可以将需要提供給模闆的資料以字典的格式添加進去。
      • 使用Python内置的

        locals()

        方法,可以友善的将函數作用域内的所有變量一次性添加。
    • content_type:用于生成的文檔的MIME類型。 預設為DEFAULT_CONTENT_TYPE設定的值。
    • status:響應的狀态代碼。 預設為200。
    • using:用于加載模闆使用的模闆引擎的NAME。

範例:

  • index.html

    檔案:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>index</title>
</head>
<body>
    <h1>首頁歡迎你,簡單模拟首頁頁面用<h1>
        <p>目前時間為:{{ time }}</p>
</body>
</html>
           
  • views.py

    相關視圖函數部分
def index(request):
    now = datetime.datetime.now().ctime()
    print(now)
    return render(request, 'index.html', {"time": now})
           

效果就是使用者通路首頁的時候,視圖函數從templates中找到index.html渲染并傳回給使用者。

其中擷取目前時間的資料是使用了相關的文法,

類似字典,time在html中充當了key,now變量為value并最終渲染到key占據的位置上。

可以想像成在圖書館裡提前替未到的另一半占位置的一對戀人。

redirect()

  • 文法

    redirect(to, permanent=False, args, *kwargs)[source]

根據傳遞進來的url參數,傳回HttpResponseRedirect。

通俗的說就是跳轉或叫重定向到傳入的位址。

可以想像為水上樂園的滑道,本來你排着隊是要滑到水池下的,

但滑的中途整個管道被人為的折彎了N度滑向了另外一個泳池,這就是重定向。

  • 參數to:
    • 一個模型:将調用模型的

      get_absolute_url()

      函數,反向解析出目的url;
    • 視圖名稱:可能帶有參數:

      reverse()

      将用于反向解析url;
    • 一個絕對的或相對的URL:将原封不動的作為重定向的目标位置。

預設情況下是臨時重定向,如果設定permanent=True将永久重定向。

範例:

  • views.py

    相關視圖函數部分
from django.shortcuts import redirect,render
from django.urls import reverse

def login(request):
    if request.method == "POST":
        # 當請求類型為post時
        username = request.POST.get("user")
        password = request.POST.get("pwd")
        # 簡單模拟資料庫驗證,通過驗證時跳轉到首頁
        if username == 'tielemao' and password == '123':
            # 寫死方式: return redirect('/index/')
            # 使用反向解析如下,
            # reverse方法用于将index别名解析回/index/
            return redirect(reverse("index"))
    return render(request, 'login.html')
           

臨時重定向HTTP狀态碼是302,永久重定向HTTP狀态碼是301,兩者主要差別是在搜尋引擎方面。

上面的例子為使用者get請求通路login的時候,傳回的是login.html頁面。

而當使用者通過form表單填寫了使用者名和密碼送出post請求并通過驗證之後,

就會被redirect跳轉(重定向)到reverse反向解析的index頁面上。

效果如gif圖:

Django視圖層Django視圖層
  • 301和302的差別。
    • 共同點:
      • 301和302狀态碼都表示重定向;
      • 浏覽器在拿到伺服器傳回的這個狀态碼後會自動跳轉到一個新的URL位址,這個位址可以從響應的Location首部中擷取
      • 使用者看到的效果就是他輸入的位址A瞬間變成了另一個位址B
    • 不同點:
      • 301表示舊位址A的資源已經被永久地移除了(這個資源不可通路了),搜尋引擎在抓取新内容的同時也将舊的網址交換為重定向之後的網址;
      • 302表示舊位址A的資源還在(仍然可以通路),這個重定向隻是臨時地從舊位址A跳轉到位址B,搜尋引擎會抓取新的内容而儲存舊的網址。
      • 對SEO來說302好于301。
    • 重定向原因:
      • 網站調整(如改變網頁目錄結構);
      • 網頁被移到一個新位址;
      • 網頁擴充名改變(如應用需要把.php改成.Html或.shtml)。

        這種情況下,如果不做重定向,則使用者收藏夾或搜尋引擎資料庫中舊位址隻能讓通路客戶得到一個404頁面錯誤資訊,通路流量白白喪失;

      • 某些注冊了多個域名的網站,也需要通過重定向讓通路這些域名的使用者自動跳轉到主站點等。

get_object_or_404()

  • 文法

    get_object_or_404(klass, args, *kwargs)[source]

這個方法,非常有用,請一定熟記。

常用于查詢某個對象,找到了則進行下一步處理,如果未找到則給使用者傳回404頁面。

在背景,Django其實是調用了模型管理器的

get()

方法,隻會傳回一個對象。

不同的是,如果

get()

發生異常,會引發Http404異常,進而傳回404頁面,而不是模型的DoesNotExist異常。

  • 必需參數:
    • klass:要擷取的對象的Model類名或者Queryset等;
    • **kwargs

      : 查詢的參數,格式應該可以被

      get()

      接受。

範例:

  • 1.從MyModel中使用主鍵1來擷取對象:
from django.shortcuts import get_object_or_404

def my_view(request):
    my_object = get_object_or_404(MyModel, pk=)
           

這個示例等同于:

from django.http import Http404

def my_view(request):
    try:
        my_object = MyModel.objects.get(pk=)
    except MyModel.DoesNotExist:
        raise Http404("No MyModel matches the given query.")
           
  • 2.除了傳遞Model名稱,還可以傳遞一個QuerySet執行個體:
queryset = Book.objects.filter(title__startswith='M')
get_object_or_404(queryset, pk=)
           

上面的示例不夠簡潔,因為它等同于:

get_object_or_404(Book, title__startswith='M', pk=1)

但是如果你的queryset來自其它地方,它就會很有用了。

  • 3.還可以使用Manager。 如果你自定義了管理器,這将很有用:

get_object_or_404(Book.dahl_objects, title='Matilda')

  • 4.還可以使用related managers:
author = Author.objects.get(name='Roald Dahl')
get_object_or_404(author.book_set, title='Matilda')
           

get()

一樣,如果找到多個對象将引發一個MultipleObjectsReturned異常。

get_list_or_404()

  • 文法

    get_list_or_404(klass, args, *kwargs)[source]

這其實就是get_object_or_404多值擷取版本。

在背景,傳回一個給定模型管理器上

filter()

的結果,并将結果映射為一個清單,如果結果為空則彈出Http404異常。

  • 必需參數:
    • klass:擷取該清單的一個Model、Manager或QuerySet執行個體。
    • **kwargs

      :查詢的參數,格式應該可以被

      filter()

      接受。

範例:

下面的示例從MyModel中擷取所有釋出出來的對象:

from django.shortcuts import get_list_or_404

def my_view(request):
    my_objects = get_list_or_404(MyModel, published=True)
           

這個示例等同于:

from django.http import Http404

def my_view(request):
    my_objects = list(MyModel.objects.filter(published=True))
    if not my_objects:
        raise Http404("No MyModel matches the given query.")
           

關于raise:

在Python中,要想引發異常,最簡單的形式就是輸入關鍵字raise,後跟要引發的異常的名稱。

【end】

參考引用:

http://www.liujiangblog.com/course/django/137

http://www.liujiangblog.com/course/django/138