Django框架-Django視圖(views)系統

Django的視圖系統

定義:一個視圖函數(或類),簡稱爲視圖,是一個簡單的python函數或類,它接受web請求而且返回web響應。html

響應能夠是一張網頁的html內容,一個重定向,一個404錯誤,一個xml文檔,或一張圖片。python

不管視圖自己包含什麼邏輯,都要返回響應,代碼寫在那裏都無所謂,只要它在你當前項目目錄下面。爲了將代碼放在某處,你們預約成俗將視圖放在項目project或應用程序app目錄中的名爲views.py的文件中。web

一、每一個視圖函數,都使用HttpRequest對象做爲第一個參數,而且一般稱之爲request。ajax

二、每一個視圖函數,都會返回一個HttpResponse對象,其中包含生成的響應。django

Django使用請求和響應對象來經過系統傳遞狀態。json

當瀏覽器向服務端請求一個頁面是,Django建立一個HttpRequest對象,該對象包含關於請求的元數據,而後,Django加載相應的視圖,將這個HttpRequest對象做爲第一個參數傳遞給視圖函數,每一個視圖函數負責返回一個HttpResponse對象。瀏覽器

常見的render,redirect,HttpResponse對象返回的都是一個HttpResponse對象。緩存

Django中視圖編碼分類

主要分爲兩類:FBV(建立視圖函數)和CBV(建立視圖類)安全

FBV(function based view):就是將業務邏輯寫在一個函數中

-----views.py
1
from django.shortcuts import render,Httpresponse,redirect 2 from app_name import models 3 4 def add_class(request): 5 if request.method =='POST': 6 class_name = request.POST.get('class_name') 7 models.Classes.objects.create(name=class_name) 8 return redirect('/class_list/') 9 return render(request,'add_class.html')

----urls.py
1 from app_name from views
2 urlpatterns = [
3  url(r'^addclass/$',views.add_class),]

CBV(class  based view): 就是以類的方式寫

-----views.py
1
from django.views import View 2 from app_name import models 3 4 class Add_class(View): # 必須繼承類View 5 6 def get(self,request): 7 return render(request,'add_class.html') 8 9 10 def post(self,request): 11 class_name = request.POST.get('class_name') 12 models.Classes.objects.create(name=class_name) 13 return tedirect('/class_list/')

使用CBV時,urls.py中也作對應的修改:服務器

1 # urls.py中
2 url(r'^add_class/$', views.AddClass.as_view()),

CBV的流程:  

一、views.AddClass.as_view()    ===》返回view函數對象

二、請求到來的時候執行view函數

  2.一、實例化AddClass,賦值給self

    self.reuest= request

  2.二、執行self.dispatch方法(AddClass若是有,執行本身的,沒有的話執行View的)

    2.2.一、判斷請求方法是否被容許

      經過反射獲取到請求方法類型

      容許:

      handler = getattr(self, request.method.lower(), self.http_method_not_allowed)

       不容許:

       拿到一個http_method_not_allowed方法

    2.2.二、執行獲取到的方法類型對應類中定義的方法,get(request,)或post(request,)

    2.2.三、獲得httpResponse對象對象,返回給self.dispatch

    2.2.四、獲得HttpResponse對象,返回django處理

給視圖加裝飾器

一、FBV加裝飾器

操做:直接在函數上方加裝飾器  @wrapper_name

二、CBV加裝飾器

必須導入:from django.utils.decorators import method_decorator

操做:三種方案

  2.一、直接在方法上加:  

1 @method_decorator(wapper_name)
2 def  get(self,request):pass

  2.二、給自定義的dispatch方法加:

1 @method_decorator(wrapper_name)
2 def  dispatch(self,request,*args,**kwargs)

  2.三、給類加

1 # 直接在類上面加
2 @method_decorator(wapper_name, name='post')    #給方法post加裝飾器
3 @method_decorator(wapper_name, name='get')
4 class AddClass(View)
5 
6 注:其實也能夠直接給View中的dispatch方法加裝飾器,這樣一樣能夠實現給本身類下的全部方法加裝飾器(本身未定義dispatch方法時)
7 @method_decorator(wapper_name, name='dispatch')
8 class AddClass(View)

注:爲視圖加裝飾器豁免單個或保護csrf_token:  from django.views.decorators.csrf import csrf_exempt,csrf_protect

在FBV能夠直接上加@csrf_exempt, 但在CBV上必須在類上加且只能給dispatch方法加。

Requset對象和Respondse對象

request對象

當一個頁面被請求時,Django就會船艦一個包含本次請求原信息的HttpReques對象。

Django會將這個對象自動傳遞給響應的視圖函數,通常視圖函數預約俗稱的使用request參數承接這個對象。

請求相關的經常使用值

  • path_info   返回用戶訪問的url,不包含域名,僅path不帶參數     /index/
  • path            同上
  • get_full_path()     返回完整路徑,不含域名   /midd/index/?wd=333&key=3333
  • method       請求中使用的HTTP方法的字符串表示,全大寫表示
  • GET             包含全部HTTP  GET參數的類字典對象
  • POST        包含全部HTTP  POST參數的類字典對象
  • body            請求體,byte類型的request.POST的數據就是從body裏面提取到的
  • FILES          上傳文件,{}    注意form標籤加enctype="multipart/form-data"屬性
  • HTTP_REFERER   跳轉到上次訪問的頁面,用戶在未登陸前要訪問的頁面,登陸後跳轉到該頁面, redirect(request.Meta.get('HTTP_REFERER','')
    HTTP_REFERER

屬性

全部的屬性應該被認爲是隻讀的,除非另有說明。

  1 屬性:
  2   django將請求報文中的請求行、頭部信息、內容主體封裝成 HttpRequest 類中的屬性。
  3    除了特殊說明的以外,其餘均爲只讀的。
  4 
  5 
  6 0.HttpRequest.scheme
  7    表示請求方案的字符串(一般爲http或https)
  8 
  9 1.HttpRequest.body
 10 
 11   一個字符串,表明請求報文的主體。在處理非 HTTP 形式的報文時很是有用,例如:二進制圖片、XML,Json等。
 12 
 13   可是,若是要處理表單數據的時候,推薦仍是使用 HttpRequest.POST 。
 14 
 15   另外,咱們還能夠用 python 的類文件方法去操做它,詳情參考 HttpRequest.read() 。
 16 
 17  
 18 
 19 2.HttpRequest.path
 20 
 21   一個字符串,表示請求的路徑組件(不含域名)。
 22 
 23   例如:"/music/bands/the_beatles/"
 24 
 25 
 26 
 27 3.HttpRequest.method
 28 
 29   一個字符串,表示請求使用的HTTP 方法。必須使用大寫。
 30 
 31   例如:"GET""POST"
 32 
 33  
 34 
 35 4.HttpRequest.encoding
 36 
 37   一個字符串,表示提交的數據的編碼方式(若是爲 None 則表示使用 DEFAULT_CHARSET 的設置,默認爲 'utf-8')。
 38    這個屬性是可寫的,你能夠修改它來修改訪問表單數據使用的編碼。
 39    接下來對屬性的任何訪問(例如從 GET 或 POST 中讀取數據)將使用新的 encoding 值。
 40    若是你知道表單數據的編碼不是 DEFAULT_CHARSET ,則使用它。
 41 
 42  
 43 
 44 5.HttpRequest.GET 
 45 
 46   一個相似於字典的對象,包含 HTTP GET 的全部參數。詳情請參考 QueryDict 對象。
 47 
 48  
 49 
 50 6.HttpRequest.POST
 51 
 52   一個相似於字典的對象,若是請求中包含表單數據,則將這些數據封裝成 QueryDict 對象。
 53 
 54   POST 請求能夠帶有空的 POST 字典 —— 若是經過 HTTP POST 方法發送一個表單,可是表單中沒有任何的數據,QueryDict 對象依然會被建立。
 55    所以,不該該使用 if request.POST  來檢查使用的是不是POST 方法;應該使用 if request.method == "POST" 
 56 
 57   另外:若是使用 POST 上傳文件的話,文件信息將包含在 FILES 屬性中。
 58 
 59  7.HttpRequest.COOKIES
 60 
 61   一個標準的Python 字典,包含全部的cookie。鍵和值都爲字符串。
 62 
 63  
 64 
 65 8.HttpRequest.FILES
 66 
 67   一個相似於字典的對象,包含全部的上傳文件信息。
 68    FILES 中的每一個鍵爲<input type="file" name="" /> 中的name,值則爲對應的數據。
 69 
 70   注意,FILES 只有在請求的方法爲POST 且提交的<form> 帶有enctype="multipart/form-data" 的狀況下才會
 71    包含數據。不然,FILES 將爲一個空的相似於字典的對象。
 72 
 73  
 74 
 75 9.HttpRequest.META
 76 
 77    一個標準的Python 字典,包含全部的HTTP 首部。具體的頭部信息取決於客戶端和服務器,下面是一些示例:
 78 
 79     CONTENT_LENGTH —— 請求的正文的長度(是一個字符串)。
 80     CONTENT_TYPE —— 請求的正文的MIME 類型。
 81     HTTP_ACCEPT —— 響應可接收的Content-Type。
 82     HTTP_ACCEPT_ENCODING —— 響應可接收的編碼。
 83     HTTP_ACCEPT_LANGUAGE —— 響應可接收的語言。
 84     HTTP_HOST —— 客服端發送的HTTP Host 頭部。
 85     HTTP_REFERER —— Referring 頁面。
 86     HTTP_USER_AGENT —— 客戶端的user-agent 字符串。
 87     QUERY_STRING —— 單個字符串形式的查詢字符串(未解析過的形式)。
 88     REMOTE_ADDR —— 客戶端的IP 地址。
 89     REMOTE_HOST —— 客戶端的主機名。
 90     REMOTE_USER —— 服務器認證後的用戶。
 91     REQUEST_METHOD —— 一個字符串,例如"GET""POST" 92     SERVER_NAME —— 服務器的主機名。
 93     SERVER_PORT —— 服務器的端口(是一個字符串)。
 94    從上面能夠看到,除 CONTENT_LENGTH 和 CONTENT_TYPE 以外,請求中的任何 HTTP 首部轉換爲 META 的鍵時,
 95     都會將全部字母大寫並將鏈接符替換爲下劃線最後加上 HTTP_  前綴。
 96     因此,一個叫作 X-Bender 的頭部將轉換成 META 中的 HTTP_X_BENDER 鍵。
 97 
 98  
 99 10.HttpRequest.user
100 
101   一個 AUTH_USER_MODEL 類型的對象,表示當前登陸的用戶。
102 
103   若是用戶當前沒有登陸,user 將設置爲 django.contrib.auth.models.AnonymousUser 的一個實例。你能夠經過 is_authenticated() 區分它們。
104 
105     例如:
106 
107     if request.user.is_authenticated():
108         # Do something for logged-in users.
109     else:
110         # Do something for anonymous users.
111      
112 
113        user 只有當Django 啓用 AuthenticationMiddleware 中間件時纔可用。
114 
115      -------------------------------------------------------------------------------------
116 
117     匿名用戶
118     class models.AnonymousUser
119 
120     django.contrib.auth.models.AnonymousUser 類實現了django.contrib.auth.models.User 接口,但具備下面幾個不一樣點:
121 
122     id 永遠爲None。
123     username 永遠爲空字符串。
124     get_username() 永遠返回空字符串。
125     is_staff 和 is_superuser 永遠爲False。
126     is_active 永遠爲 False。
127     groups 和 user_permissions 永遠爲空。
128     is_anonymous() 返回True 而不是False。
129     is_authenticated() 返回False 而不是True。
130     set_password()、check_password()、save() 和delete() 引起 NotImplementedError。
131     New in Django 1.8:
132     新增 AnonymousUser.get_username() 以更好地模擬 django.contrib.auth.models.User。
133 
134  
135 
136 11.HttpRequest.session
137 
138    一個既可讀又可寫的相似於字典的對象,表示當前的會話。只有當Django 啓用會話的支持時纔可用。
139     完整的細節參見會話的文檔。
request屬性相關

方法

 1 1.HttpRequest.get_host()
 2 
 3   根據從HTTP_X_FORWARDED_HOST(若是打開 USE_X_FORWARDED_HOST,默認爲False)和 HTTP_HOST 頭部信息返回請求的原始主機。
 4    若是這兩個頭部沒有提供相應的值,則使用SERVER_NAME 和SERVER_PORT,在PEP 3333 中有詳細描述。
 5 
 6   USE_X_FORWARDED_HOST:一個布爾值,用於指定是否優先使用 X-Forwarded-Host 首部,僅在代理設置了該首部的狀況下,才能夠被使用。
 7 
 8   例如:"127.0.0.1:8000"
 9 
10   注意:當主機位於多個代理後面時,get_host() 方法將會失敗。除非使用中間件重寫代理的首部。
11 
12  
13 
14 2.HttpRequest.get_full_path()
15 
16   返回 path,若是能夠將加上查詢字符串。
17 
18   例如:"/music/bands/the_beatles/?print=true"
19 
20  
21 
22 3.HttpRequest.get_signed_cookie(key, default=RAISE_ERROR, salt='', max_age=None)
23 
24   返回簽名過的Cookie 對應的值,若是簽名再也不合法則返回django.core.signing.BadSignature。
25 
26   若是提供 default 參數,將不會引起異常並返回 default 的值。
27 
28   可選參數salt 能夠用來對安全密鑰強力攻擊提供額外的保護。max_age 參數用於檢查Cookie 對應的時間戳以確保Cookie 的時間不會超過max_age 秒。
29 
30         複製代碼
31         >>> request.get_signed_cookie('name')
32         'Tony'
33         >>> request.get_signed_cookie('name', salt='name-salt')
34         'Tony' # 假設在設置cookie的時候使用的是相同的salt
35         >>> request.get_signed_cookie('non-existing-cookie')
36         ...
37         KeyError: 'non-existing-cookie'    # 沒有相應的鍵時觸發異常
38         >>> request.get_signed_cookie('non-existing-cookie', False)
39         False
40         >>> request.get_signed_cookie('cookie-that-was-tampered-with')
41         ...
42         BadSignature: ...    
43         >>> request.get_signed_cookie('name', max_age=60)
44         ...
45         SignatureExpired: Signature age 1677.3839159 > 60 seconds
46         >>> request.get_signed_cookie('name', False, max_age=60)
47         False
48         複製代碼
49          
50 
51 
52 4.HttpRequest.is_secure()
53 
54   若是請求時是安全的,則返回True;即請求通是過 HTTPS 發起的。
55 
56  
57 
58 5.HttpRequest.is_ajax()
59 
60   若是請求是經過XMLHttpRequest 發起的,則返回True,方法是檢查 HTTP_X_REQUESTED_WITH 相應的首部是不是字符串'XMLHttpRequest'61 
62   大部分現代的 JavaScript 庫都會發送這個頭部。若是你編寫本身的 XMLHttpRequest 調用(在瀏覽器端),你必須手工設置這個值來讓 is_ajax() 能夠工做。
63 
64   若是一個響應須要根據請求是不是經過AJAX 發起的,而且你正在使用某種形式的緩存例如Django 的 cache middleware, 
65    你應該使用 vary_on_headers('HTTP_X_REQUESTED_WITH') 裝飾你的視圖以讓響應可以正確地緩存。
請求相關方法

注意:鍵值對的值是多個的時候,好比checkbox類型的input標籤,select標籤,須要用:

request.POST.getlist("hobby")

上傳文件示例

def upload(request):
    """
    保存上傳文件前,數據須要存放在某個位置。默認當上傳文件小於2.5M時,django會將上傳文件的所有內容讀進內存。從內存讀取一次,寫磁盤一次。
    但當上傳文件很大時,django會把上傳文件寫到臨時文件中,而後存放到系統臨時文件夾中。
    :param request: 
    :return: 
    """
    if request.method == "POST":
        # 從請求的FILES中獲取上傳文件的文件名,file爲頁面上type=files類型input的name屬性值
        filename = request.FILES["file"].name
        # 在項目目錄下新建一個文件
        with open(filename, "wb") as f:
            # 從上傳的文件對象中一點一點讀
            for chunk in request.FILES["file"].chunks():
                # 寫入本地文件
                f.write(chunk)
        return HttpResponse("上傳OK")

Respondse對象

與由Django自動建立的HttpRequest對象相比,HttpResponse對象是咱們的職責範圍了。咱們寫的每一個視圖都須要實例化,填充和返回一個HttpResponse。

HttpResponse類位於django.http模塊中。

使用

傳遞字符串

from django.http import HttpResponse
response = HttpResponse("Here's the text of the Web page.")
response = HttpResponse("Text only, please.", content_type="text/plain")

設置或刪除響應頭信息

response = HttpResponse()
response['Content-Type'] = 'text/html; charset=UTF-8'
del response['Content-Type']

屬性

HttpResponse.content:響應內容

HttpResponse.charset:響應內容的編碼

HttpResponse.status_code:響應的狀態碼

JsonResponse對象

JsonResponse是HttpResponse的子類,專門用來生成JSON編碼的響應。

from django.http import JsonResponse

response = JsonResponse({'foo': 'bar'})
print(response.content)

b'{"foo": "bar"}'

默認只能傳遞字典類型,若是要傳遞非字典類型須要設置一下safe關鍵字參數。

response = JsonResponse([1, 2, 3], safe=False)

render()

結合一個給定的模板和一個給定的上下文字典,並返回一個渲染後的 HttpResponse 對象。

參數:

  • request: 用於生成響應的請求對象。
  • template_name:要使用的模板的完整名稱,可選的參數
  • context:添加到模板上下文的一個字典。默認是一個空字典。若是字典中的某個值是可調用的,視圖將在渲染模板以前調用它。
  • content_type:生成的文檔要使用的MIME類型。默認爲 DEFAULT_CONTENT_TYPE 設置的值。默認爲'text/html'
  • status:響應的狀態碼。默認爲200。
  • useing: 用於加載模板的模板引擎的名稱。

一個簡單的例子:

from django.shortcuts import render

def my_view(request):
    # 視圖的代碼寫在這裏
    return render(request, 'myapp/index.html', {'foo': 'bar'})

上面的代碼等於:

from django.http import HttpResponse
from django.template import loader

def my_view(request):
    # 視圖代碼寫在這裏
    t = loader.get_template('myapp/index.html')
    c = {'foo': 'bar'}
    return HttpResponse(t.render(c, request))

redirect()

參數能夠是:

  • 一個模型:將調用模型的get_absolute_url() 函數
  • 一個視圖,能夠帶有參數:將使用urlresolvers.reverse 來反向解析名稱
  • 一個絕對的或相對的URL,將原封不動的做爲重定向的位置。

默認返回一個臨時的重定向;傳遞permanent=True 能夠返回一個永久的重定向。

示例:

你能夠用多種方式使用redirect() 函數。

傳遞一個具體的ORM對象(瞭解便可)

將調用具體ORM對象的get_absolute_url() 方法來獲取重定向的URL:

from django.shortcuts import redirect
 
def my_view(request):
    ...
    object = MyModel.objects.get(...)
    return redirect(object)

傳遞一個視圖的名稱

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

傳遞要重定向到的一個具體的網址

def my_view(request):
    ...
    return redirect('/some/url/')

固然也能夠是一個完整的網址

def my_view(request):
    ...
    return redirect('http://example.com/')

默認狀況下,redirect() 返回一個臨時重定向。以上全部的形式都接收一個permanent 參數;若是設置爲True,將返回一個永久的重定向:

def my_view(request):
    ...
    object = MyModel.objects.get(...)
    return redirect(object, permanent=True)  

擴展閱讀: 

臨時重定向(響應狀態碼:302)和永久重定向(響應狀態碼:301)對普通用戶來講是沒什麼區別的,它主要面向的是搜索引擎的機器人。

A頁面臨時重定向到B頁面,那搜索引擎收錄的就是A頁面。

A頁面永久重定向到B頁面,那搜索引擎收錄的就是B頁面。

小結:

 response  ——》httpresponse對象

一、HttpResponse(‘字符串’)    ----》頁面顯示字符串內容   【Content-Type : text/html;charset=utf8】

二、render(request,‘模板文件名’,{}) ----》返回一個完整的頁面

三、redirect(‘/index/’)     跳轉,重定向   Location:/index/

4.JsonResponse(dict)   ———》 Content-Type:application/json

重點擴展:

視圖分發:在本身的app中創建views文件夾,裏面寫視圖py文件,須要將app中的原views.py刪除!

相關文章
相關標籤/搜索