Django 視圖系統

      網友投稿 749 2025-03-31

      一、django的View(視圖)


      一個視圖函數(類),簡稱視圖,是一個簡單的Python 函數(類),它接受Web請求并且返回Web響應。

      響應可以是一張網頁的HTML內容,一個重定向,一個404錯誤,一個XML文檔,或者一張圖片。

      無論視圖本身包含什么邏輯,都要返回響應。代碼寫在哪里也無所謂,只要它在你當前項目目錄下面。除此之外沒有更多的要求了——可以說“沒有什么神奇的地方”。為了將代碼放在某處,大家約定成俗將視圖放置在項目(project)或應用程序(app)目錄中的名為views.py的文件中。

      1、一個簡單的視圖

      下面是一個以HTML文檔的形式返回當前日期和時間的視圖:

      from?django.http?import?HttpResponse import?datetime def?current_datetime(request): ????now?=?datetime.datetime.now() ????html?=?"It?is?now?%s."?%?now ????return?HttpResponse(html)

      讓我們來逐行解釋下上面的代碼:

      首先,我們從?django.http模塊導入了HttpResponse類,以及Python的datetime庫。

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

      注意,視圖函數的名稱并不重要;不需要用一個統一的命名方式來命名,以便讓Django識別它。我們將其命名為current_datetime,是因為這個名稱能夠比較準確地反映出它實現的功能。

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

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

      當瀏覽器向服務端請求一個頁面時,Django創建一個HttpRequest對象,該對象包含關于請求的元數據。然后,Django加載相應的視圖,將這個HttpRequest對象作為第一個參數傳遞給視圖函數。

      每個視圖負責返回一個HttpResponse對象。

      2、CBV和FBV

      我們之前寫過的都是基于函數的view,就叫FBV。還可以把view寫成基于類的。

      就拿我們之前寫過的添加班級為例:

      1)、FBV版:

      #?FBV版添加班級 def?add_class(request): ????if?request.method?==?"POST": ????????class_name?=?request.POST.get("class_name") ????????models.Classes.objects.create(name=class_name) ????????return?redirect("/class_list/") ????return?render(request,?"add_class.html")

      2)、CBV版:

      #?CBV版添加班級 from?django.views?import?View class?AddClass(View): ????def?get(self,?request): ????????return?render(request,?"add_class.html") ????def?post(self,?request): ????????class_name?=?request.POST.get("class_name") ????????models.Classes.objects.create(name=class_name) ????????return?redirect("/class_list/")

      注意:

      使用CBV時,urls.py中也做對應的修改:

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

      3、給視圖加裝飾器

      Django 視圖系統

      1)、使用裝飾器裝飾FBV

      FBV本身就是一個函數,所以和給普通的函數加裝飾器無差:

      def?wrapper(func): ????def?inner(*args,?**kwargs): ????????start_time?=?time.time() ????????ret?=?func(*args,?**kwargs) ????????end_time?=?time.time() ????????print("used:",?end_time-start_time) ????????return?ret ????return?inner #?FBV版添加班級 @wrapper def?add_class(request): ????if?request.method?==?"POST": ????????class_name?=?request.POST.get("class_name") ????????models.Classes.objects.create(name=class_name) ????????return?redirect("/class_list/") ????return?render(request,?"add_class.html")

      2)、使用裝飾器裝飾CBV

      類中的方法與獨立函數不完全相同,因此不能直接將函數裝飾器應用于類中的方法 ,我們需要先將其轉換為方法裝飾器。

      Django中提供了method_decorator裝飾器用于將函數裝飾器轉換為方法裝飾器。

      #?CBV版添加班級 from?django.views?import?View from?django.utils.decorators?import?method_decorator class?AddClass(View): ????@method_decorator(wrapper) ????def?get(self,?request): ????????return?render(request,?"add_class.html") ????def?post(self,?request): ????????class_name?=?request.POST.get("class_name") ????????models.Classes.objects.create(name=class_name) ????????return?redirect("/class_list/")

      關于CBV的擴展閱讀:

      #?使用CBV時要注意,請求過來后會先執行dispatch()這個方法,如果需要批量對具體的請求處理方法,如get,post等做一些操作的時候,這里我們可以手動改寫dispatch方法,這個dispatch方法就和在FBV上加裝飾器的效果一樣。 class?Login(View):??? ????def?dispatch(self,?request,?*args,?**kwargs): ????????print('before') ????????obj?=?super(Login,self).dispatch(request,?*args,?**kwargs) ????????print('after') ????????return?obj ????def?get(self,request): ????????return?render(request,'login.html')? ????def?post(self,request): ????????print(request.POST.get('user')) ????????return?HttpResponse('Login.post')

      二、Request對象和Response對象

      1、request對象

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

      Django會將這個對象自動傳遞給響應的視圖函數,一般視圖函數約定俗成地使用 request 參數承接這個對象。

      官方文檔

      1)、請求相關的常用值

      path_info???? 返回用戶訪問url,不包括域名

      method????????請求中使用的HTTP方法的字符串表示,全大寫表示。

      GET??????????????包含所有HTTP ?GET參數的類字典對象

      POST???????????包含所有HTTP POST參數的類字典對象

      body????????????請求體,byte類型 request.POST的數據就是從body里面提取到的

      2)、屬性

      所有的屬性應該被認為是只讀的,除非另有說明。

      request屬性相關:

      屬性:   django將請求報文中的請求行、頭部信息、內容主體封裝成?HttpRequest?類中的屬性。 ???除了特殊說明的之外,其他均為只讀的。 0.HttpRequest.scheme ???表示請求方案的字符串(通常為http或https) 1.HttpRequest.body   一個字符串,代表請求報文的主體。在處理非?HTTP?形式的報文時非常有用,例如:二進制圖片、XML,Json等。   但是,如果要處理表單數據的時候,推薦還是使用?HttpRequest.POST?。   另外,我們還可以用?python?的類文件方法去操作它,詳情參考?HttpRequest.read()?。 2.HttpRequest.path   一個字符串,表示請求的路徑組件(不含域名)。   例如:"/music/bands/the_beatles/" 3.HttpRequest.method   一個字符串,表示請求使用的HTTP?方法。必須使用大寫。   例如:"GET"、"POST" 4.HttpRequest.encoding   一個字符串,表示提交的數據的編碼方式(如果為?None?則表示使用?DEFAULT_CHARSET?的設置,默認為?'utf-8')。 ???這個屬性是可寫的,你可以修改它來修改訪問表單數據使用的編碼。 ???接下來對屬性的任何訪問(例如從?GET?或?POST?中讀取數據)將使用新的?encoding?值。 ???如果你知道表單數據的編碼不是?DEFAULT_CHARSET?,則使用它。? 5.HttpRequest.GET?   一個類似于字典的對象,包含?HTTP?GET?的所有參數。詳情請參考?QueryDict?對象。 6.HttpRequest.POST   一個類似于字典的對象,如果請求中包含表單數據,則將這些數據封裝成?QueryDict?對象。   POST?請求可以帶有空的?POST?字典?——?如果通過?HTTP?POST?方法發送一個表單,但是表單中沒有任何的數據,QueryDict?對象依然會被創建。 ???因此,不應該使用?if?request.POST??來檢查使用的是否是POST?方法;應該使用?if?request.method?==?"POST"?   另外:如果使用?POST?上傳文件的話,文件信息將包含在?FILES?屬性中。 ?7.HttpRequest.COOKIES   一個標準的Python?字典,包含所有的cookie。鍵和值都為字符串。 8.HttpRequest.FILES   一個類似于字典的對象,包含所有的上傳文件信息。 ???FILES?中的每個鍵為?中的name,值則為對應的數據。   注意,FILES?只有在請求的方法為POST?且提交的

      ?帶有enctype="multipart/form-data"?的情況下才會 ???包含數據。否則,FILES?將為一個空的類似于字典的對象。 9.HttpRequest.META ?  一個標準的Python?字典,包含所有的HTTP?首部。具體的頭部信息取決于客戶端和服務器,下面是一些示例: ????CONTENT_LENGTH?——?請求的正文的長度(是一個字符串)。 ????CONTENT_TYPE?——?請求的正文的MIME?類型。 ????HTTP_ACCEPT?——?響應可接收的Content-Type。 ????HTTP_ACCEPT_ENCODING?——?響應可接收的編碼。 ????HTTP_ACCEPT_LANGUAGE?——?響應可接收的語言。 ????HTTP_HOST?——?客服端發送的HTTP?Host?頭部。 ????HTTP_REFERER?——?Referring?頁面。 ????HTTP_USER_AGENT?——?客戶端的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?鍵。 10.HttpRequest.user   一個?AUTH_USER_MODEL?類型的對象,表示當前登錄的用戶。   如果用戶當前沒有登錄,user?將設置為?django.contrib.auth.models.AnonymousUser?的一個實例。你可以通過?is_authenticated()?區分它們。 ????例如: ????if?request.user.is_authenticated(): ????????#?Do?something?for?logged-in?users. ????else: ????????#?Do?something?for?anonymous?users.????? ?????  user?只有當Django?啟用?AuthenticationMiddleware?中間件時才可用。 ?????------------------------------------------------------------------------------------- ????匿名用戶 ????class?models.AnonymousUser ????django.contrib.auth.models.AnonymousUser?類實現了django.contrib.auth.models.User?接口,但具有下面幾個不同點: ????id?永遠為None。 ????username?永遠為空字符串。 ????get_username()?永遠返回空字符串。 ????is_staff?和?is_superuser?永遠為False。 ????is_active?永遠為?False。 ????groups?和?user_permissions?永遠為空。 ????is_anonymous()?返回True?而不是False。 ????is_authenticated()?返回False?而不是True。 ????set_password()、check_password()、save()?和delete()?引發?NotImplementedError。 ????New?in?Django?1.8: ????新增?AnonymousUser.get_username()?以更好地模擬?django.contrib.auth.models.User。 11.HttpRequest.session ?  一個既可讀又可寫的類似于字典的對象,表示當前的會話。只有當Django?啟用會話的支持時才可用。 ????完整的細節參見會話的文檔。

      上傳文件示例:

      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")

      3)、方法

      請求相關方法:

      1.HttpRequest.get_host()   根據從HTTP_X_FORWARDED_HOST(如果打開?USE_X_FORWARDED_HOST,默認為False)和?HTTP_HOST?頭部信息返回請求的原始主機。 ???如果這兩個頭部沒有提供相應的值,則使用SERVER_NAME?和SERVER_PORT,在PEP?3333?中有詳細描述。   USE_X_FORWARDED_HOST:一個布爾值,用于指定是否優先使用?X-Forwarded-Host?首部,僅在代理設置了該首部的情況下,才可以被使用。   例如:"127.0.0.1:8000"   注意:當主機位于多個代理后面時,get_host()?方法將會失敗。除非使用中間件重寫代理的首部。 2.HttpRequest.get_full_path()   返回?path,如果可以將加上查詢字符串。   例如:"/music/bands/the_beatles/?print=true" 3.HttpRequest.get_signed_cookie(key,?default=RAISE_ERROR,?salt='',?max_age=None)   返回簽名過的Cookie?對應的值,如果簽名不再合法則返回django.core.signing.BadSignature。   如果提供?default?參數,將不會引發異常并返回?default?的值。   可選參數salt?可以用來對安全密鑰強力攻擊提供額外的保護。max_age?參數用于檢查Cookie?對應的時間戳以確保Cookie?的時間不會超過max_age?秒。 ????????復制代碼 ????????>>>?request.get_signed_cookie('name') ????????'Tony' ????????>>>?request.get_signed_cookie('name',?salt='name-salt') ????????'Tony'?#?假設在設置cookie的時候使用的是相同的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=60) ????????... ????????SignatureExpired:?Signature?age?1677.3839159?>?60?seconds ????????>>>?request.get_signed_cookie('name',?False,?max_age=60) ????????False ????????復制代碼????????? 4.HttpRequest.is_secure()   如果請求時是安全的,則返回True;即請求通是過?HTTPS?發起的。 5.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')?裝飾你的視圖以讓響應能夠正確地緩存。

      注意:鍵值對的值是多個的時候,比如checkbox類型的input標簽,select標簽,需要用:

      request.POST.getlist("hobby")

      2、Response對象

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

      HttpResponse類位于django.http模塊中。

      1)、使用

      傳遞字符串:

      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']

      2)、屬性

      HttpResponse.content:響應內容

      HttpResponse.charset:響應內容的編碼

      HttpResponse.status_code:響應的狀態碼

      3、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)

      4、Django shortcut functions

      官方文檔

      1)、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))

      2)、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頁面。

      軟件開發 人工智能 云計算 機器學習

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      上一篇:excel篩選不全怎么回事
      下一篇:excel表格做篩選的教程(excel表格中如何做篩選)
      相關文章
      亚洲日韩精品无码专区网址| 亚洲综合激情另类专区| 亚洲AV无码精品色午夜果冻不卡 | 国产精品亚洲а∨无码播放麻豆| 亚洲一区二区三区免费在线观看| 伊人久久综在合线亚洲2019| 亚洲精品在线观看视频| 亚洲成人激情在线| 亚洲制服中文字幕第一区| 亚洲国产精品久久久久网站| 亚洲一卡2卡三卡4卡有限公司| 久久久久亚洲精品美女| 亚洲国产一区国产亚洲| 亚洲成色999久久网站| 78成人精品电影在线播放日韩精品电影一区亚洲 | 亚洲综合av一区二区三区不卡| 亚洲国产日韩视频观看| 亚洲色在线无码国产精品不卡| 亚洲熟妇无码AV| 亚洲AV无码XXX麻豆艾秋| 大桥未久亚洲无av码在线| 国产亚洲精品欧洲在线观看| 亚洲精品国产福利一二区| 中文亚洲AV片在线观看不卡| 国产亚洲一区二区手机在线观看 | 亚洲av女电影网| 亚洲精品白色在线发布| 亚洲免费在线视频观看| 亚洲国产系列一区二区三区| 亚洲爆乳成av人在线视菜奈实| 无码天堂va亚洲va在线va| 亚洲精品人成无码中文毛片| 国产亚洲精品无码拍拍拍色欲| 亚洲国产三级在线观看| 综合自拍亚洲综合图不卡区| 亚洲av成人综合网| 亚洲av无码专区在线电影天堂 | 国产一区二区三区亚洲综合| 中文字幕亚洲一区二区va在线| 亚洲AV永久无码精品一百度影院 | 亚洲毛片一级带毛片基地|