Django之視圖層

Django之視圖層

視圖函數

視圖函數,簡稱視圖,屬於Django的視圖層,默認定義在views.py文件中,是用來處理web請求信息以及返回響應信息的函數,因此研究視圖函數只需熟練掌握兩個對象便可:請求對象(HttpRequest)和響應對象(HttpResponse)php

undefined

請求對象(HttpRequest)

djangohttp協議請求報文中的請求行、首部信息、內容主體封裝到了HttpRequest對象中(相似於咱們自定義框架的environ參數)。 django會將HttpRequest對象當作參數傳給視圖函數的第一個參數request,在視圖函數中,經過訪問該對象的屬性即可以提取http協議的請求數據html

HttpRequest對象經常使用屬性part1

  1. HttpRequest.method
      獲取請求使用的方法(值爲純大寫的字符串格式)。例如:"GET""POST"
    應該經過該屬性的值來判斷請求方法前端

  2. HttpRequest.GET
      值爲一個相似於字典的QueryDict對象,封裝了GET請求的全部參數,可經過HttpRequest.GET.get(‘鍵’)獲取相對應的值python

  3. HttpRequest.POST
    值爲一個相似於字典的QueryDict對象,封裝了POST請求所包含的表單數據,可經過HttpRequest.POST.get(‘鍵’)獲取相對應的值web

    針對表單中checkbox類型的input標籤、select標籤提交的數據,鍵對應的值爲多個,須要用:HttpRequest.POST.getlist("hobbies")獲取存有多個值的列表,同理也有HttpRequest.GET.getlist(「鍵」)ajax

案例:數據庫

urls.pydjango

from django.urls import re_path
from app01 import views

urlpatterns = [
    re_path(r'^login/$',views.login),
]

Views.pyjson

from django.shortcuts import render,HttpResponse

def login(request):
    if request.method == 'GET':
        # 當請求url爲:http://127.0.0.1:8001/login/?a=1&b=2&c=3&c=4&c=5
        # 請求方法是GET,?後的請求參數都存放於request.GET中
        print(request.GET)
        # 輸出<QueryDict: {'a': ['1'], 'b': ['2'], 'c': ['3', '4', '5']}>

        # 獲取?後參數的方式爲
        a=request.GET.get('a') # 1
        b=request.GET.get('b') # 2
        c=request.GET.getlist('c') # ['3', '4', '5']

        return render(request,'login.html')
    elif request.method == 'POST':
        # 在輸入框內輸入用戶名egon、年齡18,選擇愛好,點擊提交
        # 請求方法爲POST,表單內的數據都會存放於request.POST中
        print(request.POST) 
        # 輸出<QueryDict: {..., 'name': ['egon'], 'age': ['18'], 'hobbies': ['music', 'read']}>

        # 獲取表單中數據的方式爲
        name=request.POST.get('name') # egon
        age=request.POST.get('age') # 18
        hobbies=request.POST.getlist('hobbies') # ['music', 'read']

        return HttpResponse('提交成功')

templates目錄下新建login.html瀏覽器

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>登陸頁面</title>
</head>
<body>

<!--
method="post"表明在提交表單時會以POST方法提交表單數據
action="/login/" 表明表單數據的提交地址爲http://127.0.0.1:8001/login/,能夠簡寫爲action="/login/",或者action=""
-->
<form action="http://127.0.0.1:8001/login/" method="post">
    {% csrf_token %} <!--強調:必須加上這一行,後續咱們會詳細介紹-->
    <p>用戶名:<input type="text" name="name"></p>
    <p>年齡:<input type="text" name="age"></p>
    <p>
        愛好:
        <input type="checkbox" name="hobbies" value="music">音樂
        <input type="checkbox" name="hobbies" value="read">閱讀
        <input type="checkbox" name="hobbies" value="dancing">跳舞
    </p>
    <p><input type="submit" value="提交"></p>

</form>
</body>
</html>

HttpRequest對象經常使用屬性part2

一.HttpRequest.body
   當瀏覽器基於http協議的POST方法提交數據時,數據會被放到請求體中發送給django,django會將接收到的請求體數據存放於HttpRequest.body屬性中,由於該屬性的值爲Bytes類型,因此一般狀況下直接處理Bytes、並從中提取有用數據的操做是複雜而繁瑣的,好在django會對它作進一步的處理與封裝以便咱們更爲方便地提取數據,好比
   對於form表單來講,提交數據的經常使用方法爲GET與POST
   1:若是表單屬性method='GET',那麼在提交表單時,表單內數據不會存放於請求體中,而是會將表單數據按照k1=v1&k2=v2&k3=v3的格式放到url中,而後發送給django,django會將這些數據封裝到request.GET中,注意此時的request.body爲空、無用
   2:若是表單屬性method='POST',那麼在提交表單時,表單內的全部數據都會存放於請求體中,在發送給django後會封裝到request.body裏,此時django爲了方便咱們提取數據,會request.body的數據進行進一步的處理,具體如何處理呢,須要從form表單提交數據的編碼格式提及:
    form表單對提交的表單數據有兩種經常使用的編碼格式,能夠經過屬性enctype進行設置,以下
    編碼格式1(默認的編碼格式):enctype="application/x-www-form-urlencoded" 
    編碼格式2(使用form表單上傳文件時只能用該編碼):enctype="multipart/form-data" 
    若是form表單提交數據是按照編碼格式1,那麼request.body中數據的格式相似於GET方法的數據格式,如k1=v1&k2=v2,此時django會將request.body中的數據提取出來封裝到request.POST中方便咱們提取
    若是form表單提交數據是按照編碼格式2,那麼request.body中數據的格式爲b'------WebKitFormBoundaryKtcwuksQltpNprep\r\nContent-Disposition: form-data;......',,此時django會將request.body中的數據提取出來封裝到request.POST中,將上傳的文件數據專門提取出來封裝到request.FILES屬性中
    強調:毫無疑問,編碼格式2的數據量要大於編碼格式1,若是無需上傳文件,仍是推薦使用更爲精簡的編碼格式1
    
    咱們除了能夠採用form表單向django提交數據外,還能夠採用ajax技術,ajax能夠提交的數據格式有:一、編碼格式1 二、編碼格式2 三、json,當ajax採用POST方法提交前兩種格式的數據時,django的處理方案同上,可是當ajax採用POST方法提交json格式的數據時,django會將接收到的數據存放於HttpRequest.body,此時須要咱們本身對HttpRequest.body屬性值作反序列化操做,
具體的,咱們在講解ajax時再作具體介紹
    
二.HttpRequest.FILES
   若是使用form表單POST上傳文件的話,文件數據將包含在HttpRequest.FILES屬性中。

  該屬性值爲一個相似於字典的對象,能夠包含多組key:value(對應多個上傳的文件),其中每一個key爲<input type="file" name="" /> 中name屬性的值,而value則爲對應的文件數據
  強調:HttpRequest.FILES 只有在請求的方法爲POST 且提交的<form> 帶有enctype="multipart/form-data" 的狀況下才會包含數據。不然,FILES 將爲一個空的相似於字典的對象。

undefined

案例:form表單上傳文件

urls.py

from django.urls import path,register_converter,re_path
from app01 import views

urlpatterns = [
    re_path(r'^register/$',views.register),
]

views.py

from django.shortcuts import render,HttpResponse

def register(request):
    if request.method == 'GET':
        return render(request,'register.html')
    elif request.method == 'POST':
        print(request.body)

        # 從request.POST中獲取用戶名
        name=request.POST.get('name') 
        # 從request.FILES獲取文件對象
        file_obj=request.FILES.get('header_img') 
        
        # 上傳的文件存放於templates文件夾下
        with open('templates/header.png','wb') as f: 
            for line in file_obj:
                f.write(line)

        return HttpResponse('註冊成功')

templates目錄下新建register.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>註冊頁面</title>
</head>
<body>

<form action="" method="POST" enctype="multipart/form-data" >
    {% csrf_token %}
    <p>
        用戶名:<input type="text" name="name">
    </p>
    <p>
        頭像:<input type="file" name="header_img">
    </p>
    <p>
        <input type="submit" value="提交">
    </p>
</form>
</body>
</html>

HttpRequest對象經常使用屬性part3

一.HttpRequest.path
  獲取url地址的路徑部分,只包含路徑部分

二.HttpRequest.get_full_path()
  獲取url地址的完整path,既包含路徑又包含參數部分

若是請求地址是http://127.0.0.1:8001/order/?name=egon&age=10#_label3,
HttpRequest.path的值爲"/order/"
HttpRequest.get_full_path()的值爲"/order/?name=egon&age=10"

案例:

urls.py

from django.urls import path,register_converter,re_path
from app01 import views

urlpatterns = [
    re_path(r'^order',views.order),
]

views.py

from django.shortcuts import render,HttpResponse

# 針對請求的url地址:http://127.0.0.1:8001/order/?name=egon&age=10#_label3
# 從域名後的最後一個「/」開始到「?」爲止是路徑部分,即/order/
# 從「?」開始到「#」爲止之間的部分爲參數部分,即name=egon&age=10
def order(request):
    print(request.path) # 結果爲「/order/」
    print(request.get_full_path()) # 結果爲"/order/?name=egon&age=10"

    return HttpResponse('order page')

HttpRequest對象經常使用屬性part4

undefined

一.HttpRequest.META
   值爲包含了HTTP協議的請求頭數據的Python字典,字典中的key及期對應值的解釋以下
    CONTENT_LENGTH —— 請求的正文的長度(是一個字符串)。
    CONTENT_TYPE —— 請求的正文的MIME類型。
    HTTP_ACCEPT —— 響應可接收的Content-Type。
    HTTP_ACCEPT_ENCODING —— 響應可接收的編碼。
    HTTP_ACCEPT_LANGUAGE —— 響應可接收的語言。
    HTTP_HOST —— 客服端發送數據的目標主機與端口
    HTTP_REFERER —— Referring 頁面。
    HTTP_USER_AGENT —— 客戶端使用的軟件版本信息
    QUERY_STRING —— 單個字符串形式的查詢字符串(未解析過的形式)。
    REMOTE_ADDR —— 客戶端的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 鍵。
   
注意:下述經常使用屬性暫且瞭解便可,待咱們講到專門的知識點時再專門詳細講解
二.HttpRequest.COOKIES
  一個標準的Python 字典,包含全部的cookie。鍵和值都爲字符串。

三.HttpRequest.session
  一個既可讀又可寫的相似於字典的對象,表示當前的會話。只有當Django 啓用會話的支持時纔可用。

11.HttpRequest.user(用戶認證組件下使用)

  一個 AUTH_USER_MODEL 類型的對象,表示當前登陸的用戶。

2.HttpRequest.is_ajax()

  若是請求是經過XMLHttpRequest 發起的,則返回True,方法是檢查 HTTP_X_REQUESTED_WITH 相應的首部是不是字符串'XMLHttpRequest'。

  大部分現代的 JavaScript 庫都會發送這個頭部。若是你編寫本身的 XMLHttpRequest 調用(在瀏覽器端),你必須手工設置這個值來讓 is_ajax() 能夠工做。

  若是一個響應須要根據請求是不是經過AJAX 發起的,而且你正在使用某種形式的緩存例如Django 的 cache middleware,
   你應該使用 vary_on_headers('HTTP_X_REQUESTED_WITH') 裝飾你的視圖以讓響應可以正確地緩存。

響應對象(HttpResponse)

響應能夠是任何形式的內容,好比一個HTML文件的內容,一個重定向,一個404錯誤,一個XML文檔,或者一張圖片等。總之,不管視圖自己包含什麼邏輯,都要返回響應,具體的說,響應對象主要有三種形式:HttpResponse,render,redirect

from django.shortcuts import HttpResponse,render,redirect

HttpResponse()

括號內直接跟一個具體的字符串做爲響應體,比較直接很簡單,因此這裏主要介紹後面兩種形式。

render()

render(request, template_name[, context])
參數:
    一、request:用於生成響應的請求對象,固定必須傳入的第一個參數

    二、template_name:要使用的模板的完整名稱,必須傳入,render默認會去templates目錄下查找模板文件

    三、context:可選參數,能夠傳入一個字典用來替換模塊文件中的變量

綜上,render的功能能夠總結爲:根據給定字典渲染模板文件,並返回一個渲染後的 HttpResponse對象。

redirect()

# 返回重定向信息
def my_view(request):
    ...
    return redirect('/some/url/')

# 重定向的地址也能夠是一個完整的URL:
def my_view(request):
    ...
    return redirect('http://www.baidu.com/') 

undefined

重定向轉態碼301與302的區別(瞭解)

1、301和302的異同。
   一、相同之處:
   301和302狀態碼都表示重定向,具體點說就是瀏覽器在拿到服務器返回的這個狀態碼後會自動跳轉到一個新的URL地址(瀏覽器會從響應頭Location中獲取新地址),用戶看到的效果都是輸入地址A後瞬間跳轉到了另外一個地址B
   
   二、不一樣之處:
  301表示舊地址A的資源已經被永久地移除了,即這個資源不可訪問了。搜索引擎在抓取新內容的同時也將舊的網址轉換爲重定向以後的地址;
  302表示舊地址A的資源還在,即這個資源仍然能夠訪問,這個重定向只是臨時地從舊地址A跳轉到地址B,搜索引擎會抓取新的內容、而且會保存舊的網址。 從SEO層面考慮,302要好於301

2、重定向緣由:
   一、網站調整(如改變網頁目錄結構);
   二、網頁被移到一個新地址;
   三、網頁擴展名改變(如應用須要把.php改爲.Html或.shtml)。
      這種狀況下,若是不作重定向,則用戶收藏夾或搜索引擎數據庫中舊地址只能讓訪問客戶獲得一個404頁面錯誤信息,訪問流量白白喪失;再者某些註冊了多個域名的網站,也須要經過重定向讓訪問這些域名的用戶自動跳轉到主站點等。

JsonResponse

向前端返回一個json格式字符串的兩種方式

方式一:

import json

def my_view(request):
    data=['egon','kevin']
    return HttpResponse(json.dumps(data) )

方式二:

from django.http import JsonResponse

def my_view(request):
    data=['egon','kevin']
    return JsonResponse(data,safe=False)
    #默認safe=True表明只能序列化字典對象,safe=False表明能夠序列化字典之外的對象

FBVCBV

django的視圖層由兩種形式構成:FBVCBV

  1. FBV基於函數的視圖(Function base view),咱們以前一直介紹的都是FBV
  2. CBV基於類的視圖(Class base view)

案例:

urls.py

from django.urls import path,register_converter,re_path
from app01 import views

urlpatterns = [
    re_path(r'^login/',views.LoginView.as_view()), # 必須調用類下的方法as_view
]

views.py

from django.shortcuts import render,HttpResponse,redirect
from django.views import View

class LoginView(View):
    def dispatch(self, request, *args, **kwargs): # 可在該方法內作一些預處理操做
        # 當請求url爲:http://127.0.0.1:8008/login/會先觸發dispatch的執行
        # 若是http協議的請求方法爲GET,則調用下述get方法
        # 若是http協議的請求方法爲POST,則調用下述post方法
        obj=super().dispatch(request, *args, **kwargs) # 必須繼承父類的dispatch功能
        return obj # 必須返回obj

    def get(self,request):
        return render(request,'login.html')

    def post(self,request):
        name=request.POST.get('name')
        pwd=request.POST.get('pwd')
        if name  == 'egon' and pwd == '123':
            res='登陸成功'
        else:
            res='用戶名或密碼錯誤'
        return HttpResponse(res)

測試:

python manage.py runserver 8001 
# 驗證GET請求:在瀏覽器輸入:http://127.0.0.1:8001/login/
# 驗證POST請求:在表單內輸入數據而後提交

採用CBV能夠引入面向對象的思想對數據進行更高程度的封裝,此處簡單瞭解便可,咱們將在後續的項目中詳細介紹它的應用於強大之處

undefined

相關文章
相關標籤/搜索