5.Django視圖系統(tǒng)

Django視圖系統(tǒng)

  1. Django的View

    • 一個視圖函數(shù)(類),簡稱視圖,是一個簡單的Python 函數(shù)(類),它接受Web請求并且返回Web響應(yīng)。
    • 響應(yīng)可以是網(wǎng)頁的HTML內(nèi)容,一個重定向,一個404錯誤,一個XML文檔,或者一張圖片。
    • 無論視圖本身包含什么邏輯,都要返回響應(yīng)。代碼寫在哪里也無所謂,只要它在你當(dāng)前項(xiàng)目目錄下面。除此之外沒有更多的要求了——可以說“沒有什么神奇的地方”。為了將代碼放在某處,大家約定成俗將視圖放置在項(xiàng)目(project)或應(yīng)用程序(app)目錄中的名為views.py的文件中。
    • 簡而言之,視圖,就是你寫業(yè)務(wù)邏輯的地方。

  1. 一個簡單的視圖示例

    • 下面是一個在views.py中以HTML文檔形式返回當(dāng)前日期和時間的視圖:

      from django.http import HttpResponse
      import datetime
      
      def current_datetime(request):
          now = datetime.datetime.now()
          html = "<html><body>It is now %s.</body></html>" % now
          return HttpResponse(html)
      
    • 讓我們來逐行解釋下上面的代碼:

      • 首先,我們從 django.http模塊導(dǎo)入了HttpResponse類,以及Python的datetime庫。

      • 接著,我們定義了current_datetime函數(shù)。它就是視圖函數(shù)。每個視圖函數(shù)都使用HttpRequest對象作為第一個參數(shù),并且通常稱之為request。

        注意,視圖函數(shù)的名稱并不重要;不需要用一個統(tǒng)一的命名方式來命名,以便讓Django識別它。我們將其命名為current_datetime,是因?yàn)檫@個名稱能夠比較準(zhǔn)確地反映出它實(shí)現(xiàn)的功能。

      • 這個視圖會返回一個HttpResponse對象,其中包含生成的響應(yīng)。每個視圖函數(shù)都負(fù)責(zé)返回一個HttpResponse對象。

      • Django使用請求和響應(yīng)對象來通過系統(tǒng)傳遞狀態(tài)。當(dāng)瀏覽器向服務(wù)端請求一個頁面時,Django創(chuàng)建一個HttpRequest對象,該對象包含關(guān)于請求的元數(shù)據(jù)。然后,Django加載相應(yīng)的視圖,將這個HttpRequest對象作為第一個參數(shù)傳遞給視圖函數(shù)。每個視圖負(fù)責(zé)返回一個HttpResponse對象。


  1. FBV和CBV

    • FBV:基于函數(shù)寫的view稱為FBV。

      def register(request):
          '''
          這是一個注冊頁面的函數(shù)
          :param request:
          :return:
          '''
          if request.method == 'POST':
              # 用戶提交注冊信息
              username = request.POST.get('username', None)
              # 通過models.UserInfo.objects對象在數(shù)據(jù)庫中創(chuàng)建這條記錄
              models.UserInfo.objects.create(name=username)
              # 數(shù)據(jù)創(chuàng)建成功后直接跳轉(zhuǎn)到user_list頁面
              return redirect('/user_list/')
          # 如果不為POST,則執(zhí)行下面的語句
          return render(request, 'register.html')
      
    • CBV:基于類寫的view稱為CBV。

      from django.views import View
      
      class Registrer(View):    # 需要繼承View
          
          def get(self, request):
              return render(request, 'register.html')
      
          def post(self, request):
              username = request.POST.get('username', None)
              # 通過models.UserInfo.objects對象在數(shù)據(jù)庫中創(chuàng)建這條記錄
              models.UserInfo.objects.create(name=username)
              # 數(shù)據(jù)創(chuàng)建成功后直接跳轉(zhuǎn)到user_list頁面
              return redirect('/user_list/')
      

      需要注意的是,若使用CBV,urls.py中調(diào)用類的時候必須加上.as_Views()

      # urls.py中
      from django.contrib import admin
      from django.urls import path
      from app import views
      
      urlpatterns = [
          # ......
          path('register/', views.Register.as_View()),
          # ......
      ]
      

  1. 視圖裝飾器

    • Django 提供很多裝飾器,它們可以為視圖支持多種 HTTP 特性。查看 裝飾類 來了解如何在基于類的視圖中使用這些裝飾器。

    • 允許的 HTTP 方法

      • 在 django.views.decorators.http 中的裝飾器可以用來根據(jù)請求方法來限制對視圖的訪問。如果條件不滿足,這些裝飾器將返回 django.http.HttpResponseNotAllowed 。

      • require_http_methods(request_method_list)裝飾器可以要求視圖只接受特定的請求方法。

        from django.views.decorators.http import require_http_methods
        
        @require_http_methods(["GET", "POST"])   # 注意:請求方法應(yīng)該是大寫。
        def my_view(request):
            # I can assume now that only GET or POST requests make it this far
            # ...
            pass
        
      • require_GET()裝飾器可以要求視圖只接受 GET 方法。

      • require_POST()裝飾器可以要求視圖只接受 POST 方法。

      • require_safe()裝飾器可以要求視圖只接收 GET 和 HEAD 方法。這些方法通常被認(rèn)為是安全的,因?yàn)樗鼈兂藱z索請求的資源外,沒有特別的操作。

      注解

      Web 服務(wù)器自動刪除對 HEAD 請求的相應(yīng)內(nèi)容,并保持頭部不變,所以你可以像處理視圖里的 GET 請求一樣處理 HEAD 請求。因?yàn)橐恍┸浖蕾?HEAD 請求(比如鏈接檢測器),因此你需要使用 require_safe 而不是 require_GET 。


  1. Request對象和Response對象

    • Request對象(HttpRequest的對象)

      • 當(dāng)一個頁面被請求時,Django就會創(chuàng)建一個包含本次請求原信息的HttpRequest對象。并且會將這個對象自動傳遞給響應(yīng)的視圖函數(shù),一般視圖函數(shù)約定俗成地使用 request 參數(shù)承接這個對象。在視圖函數(shù)中,接收的request常用的屬性如下:

        • request.path_info:返回用戶訪問的url,不包括域名、IP、端口和參數(shù)。

        • request.method:所使用的請求方法(GET還是POST),全大寫表示。

        • request.GET:以字典的形式獲取HTTP信息中的GET參數(shù)。

        • request.POST:以字典的形式獲取HTTP信息中的POST參數(shù)。

        • request.body: 請求體,byte類型 request.POST的數(shù)據(jù)就是從body里面提取到的。

        • request.scheme:以字符串形式獲取請求的方式(http或https)。

        • request.body:以byte形式獲取請求報(bào)文的主體。在處理非 HTTP 形式的報(bào)文時非常有用,例如:二進(jìn)制圖片、XML,Json等。

        • request.path:返回用戶訪問的url,不包括域名、IP、端口和參數(shù)。

        • request.COOKIES:一個標(biāo)準(zhǔn)的Python 字典,包含所有的cookie。鍵和值都為字符串。

        • request.FILES:一個類似于字典的對象,包含所有的上傳文件信息。

        • request.META:一個標(biāo)準(zhǔn)的Python 字典,包含所有的HTTP 首部。具體的頭部信息取決于客戶端和服務(wù)器。

          • CONTENT_LENGTH:請求的正文的長度(是一個字符串)

          • CONTENT_TYPE:請求的正文的MIME 類型

          • HTTP_ACCEPT:響應(yīng)可接收的Content-Type

          • HTTP_ACCEPT_ENCODING:響應(yīng)可接收的編碼。

          • HTTP_ACCEPT_LANGUAGE:響應(yīng)可接收的語言。

          • HTTP_HOST:客服端發(fā)送的HTTP Host 頭部。

          • HTTP_REFERER:Referring 頁面。

          • HTTP_USER_AGENT:客戶端的user-agent 字符串。

          • QUERY_STRING:單個字符串形式的查詢字符串(未解析過的形式)。

          • REMOTE_ADDR:客戶端的IP 地址。

          • REMOTE_HOST:客戶端的主機(jī)名。

          • REMOTE_USER:服務(wù)器認(rèn)證后的用戶。

          • REQUEST_METHOD:一個字符串,例如"GET" 或"POST"。

          • SERVER_NAME:服務(wù)器的主機(jī)名。

          • SERVER_PORT:服務(wù)器的端口(是一個字符串)。

            從上面可以看到,除 CONTENT_LENGTHCONTENT_TYPE之外,請求中的任何 HTTP 首部轉(zhuǎn)換為 META 的鍵時,都會將所有字母大寫并將連接符替換為下劃線最后加上HTTP_前綴。

        • request.user:一個 AUTH_USER_MODEL 類型的對象,獲取當(dāng)前登錄的用戶。

        • request.session:一個既可讀又可寫的類似于字典的對象,表示當(dāng)前的會話。只有當(dāng)Django啟用會話的支持時才可用。

      • request中常用的方法:

        • request.get_host():根據(jù)從HTTP_X_FORWARDED_HOST(如果打開 USE_X_FORWARDED_HOST,默認(rèn)為False)和 HTTP_HOST 頭部信息返回請求的原始主機(jī)。如果這兩個頭部沒有提供相應(yīng)的值,則使用SERVER_NAMESERVER_PORT,在PEP 3333 中有詳細(xì)描述。USE_X_FORWARDED_HOST是一個布爾值,用于指定是否優(yōu)先使用 X-Forwarded-Host 首部,僅在代理設(shè)置了該首部的情況下,才可以被使用。
        • request.get_full_path():不同于request.path_info,雖然不包括域名、IP、端口,但會包含參數(shù)。
        • request.get_signed_cookie(key, default=RAISE_ERROR, salt='', max_age=None):返回簽名過的Cookie 對應(yīng)的值,如果簽名不再合法則返回django.core.signing.BadSignature。
        • request.is_secure():如果請求時是安全的,則返回True;即請求通是過 HTTPS 發(fā)起的。
        • request.is_ajax():如果請求是通過XMLHttpRequest 發(fā)起的,則返回True,方法是檢查 HTTP_X_REQUESTED_WITH 相應(yīng)的首部是否是字符串XMLHttpRequest。大部分現(xiàn)代的 JavaScript 庫都會發(fā)送這個頭部。如果你編寫自己的 XMLHttpRequest 調(diào)用(在瀏覽器端),你必須手工設(shè)置這個值來讓 is_ajax() 可以工作。

  • Response對象

    • 與由Django自動創(chuàng)建的HttpRequest對象相比,HttpResponse對象是我們的職責(zé)范圍了。我們寫的每個視圖都需要實(shí)例化,填充和返回一個HttpResponse。HttpResponse類位于django.http模塊中。

  • JsonResponse對象

    • JsonResponse是HttpResponse的子類,專門用來生成JSON編碼的響應(yīng)。

      from django.http import JsonResponse
      
      def get_josn():
       data = {'foo': 'bar'}
       response = JsonResponse(data)
          # 默認(rèn)只能傳遞字典類型,如果要傳遞非字典類型需要設(shè)置一下safe關(guān)鍵字參數(shù)。response = JsonResponse(data, safe=False)
       return response
      
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
禁止轉(zhuǎn)載,如需轉(zhuǎn)載請通過簡信或評論聯(lián)系作者。

友情鏈接更多精彩內(nèi)容