国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

跟我一起Django-05URLHTTP機制和視圖

2019-11-14 17:34:10
字體:
來源:轉載
供稿:網友

定義了數據模型之后,如何通過Django來展示數據?

————模板語言和表單(下一節內容)

這個展示數據的邏輯是怎么控制的?

————控制器邏輯和URL分派機制(這是本節的內容)

先用思維導圖理理思路,再去看技術細節

http://m.survivalescaperooms.com/ganiks/

邏輯導圖導出Word結構:

URL、HTTP機制和視圖1 URL1.1 URLconf介紹1.2 用url替換元組1.3 使用多個Patterns對象1.4 用include來包含其他URL文件1.5 函數對象 v.s. 函數名字符串2 HTTP建模:請求、響應和中間件2.1 請求對象2.1.1 GET和POST字典2.1.2 Cookies和sessions2.1.3 其他服務器變量pathmethodencodingFILESMETAuserraw_post_data2.2 響應對象2.3 中間件2.3.1 請求中間件2.3.2 響應中間件3 視圖與邏輯3.1 就是Python函數3.2 通用視圖3.3 半通用視圖3.4 自定義視圖

1 URL

將一個請求的URL和結果的響應聯系起來的機制就是任何Web開發框架的關鍵所在
Django使用的是一種簡單而強大的機制, 讓你可以通過正則表達式配置映射到Python的視圖方法上,并通過互相包含把他們連接在一起

1.1 URLconf介紹

這個“映射”存放路徑一般是這樣
mysite/mysite/urls.py

from django.conf.urls import patterns, include, urlurlpatterns = patterns('mysite.myapp.views',    (r'^$', 'index'),    (r'^archives/(?P<year>/d{4})/(?P<month>/d{2})/(?P<day>/d{2})/$', 'archieve'),)

這個文件暴露一個對象urlpatterns,這個對象由函數patterns生成,并包含2點:

  • 一個,打頭的前綴字符串,可以為空 -- 'mysite.myapp.views',這個值如果not null,會被加到函數字符串之前拼接,比如這個最終完整的視圖函數路徑其實是mysite.myapp.views.index and mysite.myapp.views.archieve
  • 一個或多個元組

    • 由正則regex字符串匹配一個或一組URL -- r'^$' r'^archives/()/()/()/$'
    • 一個視圖函數對象或者字符串 -- 'index' 'archieve'
    • 有時可以帶上一個視圖函數的字典參數

注意注意:由于到處都是打頭的斜杠/,故省略。即r'^$'其實是r'^/$', 定義的就是首頁

概念:符號組 symbolic groups

這個例子中的正則表達式包含了一個很重要的概念符號組,如(?P<year>/d{4}),用來撲捉部分URL的變化,這是定義動態URL的關鍵。
后面通過撲捉的值會被傳遞到特定的視圖函數里去,然后函數會在DB查詢或是任何合適的地方使用。

下面通過4個步驟,將這個實例,將Django的URL機制持續優化

1.2 用url替換元組

上面提到url patterns定義的第二部分是一個或者多個元組,這里將元組優化成一個url方法,這個方法有4個參數,前三個對應了前面提到的三個

  • 一個正則
  • 一個視圖字符串函數
  • 一個可選的字典參數
  • 一個可選的命名參數:name -- 就是一個字符串,必須在所有的URL中保持唯一,這樣可以再別的地方引用到這個特定URL

根據url方法,重寫下

from django.conf.urls.defaults import *urlpatterns = patterns('mysite.myapp.views',    url(r'^$', 'index', name='index'),    url(r'^archives/(?P<year>/d{4})/(?P<month>/d{2})/(?P<day>/d{2})/$', 'archieve', name='archives'),)

使用url方法的意義在哪里?---原來元組中的第三個參數是個“位置參數”會讓設置變得不那么靈活;而替換之后,第三個第四個參數都是“命名參數”,你可以一個都不指定,指定一個,或者都指定,這樣就更強大和靈活了。

1.3 使用多個Patterns對象

把URL打散到多個patterns調用里,是當URL很多時一個必然的趨勢;而patterns返回的類型正好是一個Django內部對象類型,很方便被當做列表或者其他容器類型一樣附加元素,這樣就可以方便將多個這樣的對象鏈接起來

一般,會按照“前綴字符串”將所有的URL分開,在通過+=符號鏈接起來

from django.conf.urls.defaults import *urlpatterns = patterns('mysite.myapp.views',    url(r'^$', 'index'),    url(r'^blog/new/$', 'new_post'),)urlpatterns += patterns('mysite.guestbook.views',    url(r'^guestbook/$', 'index'),    url(r'^guestbook/add/$', 'new_entry'),    ...guestbook...)urlpatterns += patterns('mysite.catalog.views',    url(r'^catalog/$', 'index'),    ...catalog...)

貌似還是挺麻煩,是不是還有優化的余地?這里還是重復寫了很多次的guestbook catalog

1.4 用include來包含其他URL文件

前面一步將patterns拆分成多個patterns調用,其實還可以進一步拆分到多個urls.py文件,并讓一個主URL定義文件通過include來調用其他的子URL定義文件

##urls.py##blog/urls.py##guestbook/urls.py##catalog/urls.py
##urls.pyfrom django.conf.urls.defaults import *urlpatterns = patterns('mysite.myapp.blog.views',    url(r'^$', 'index'),    url(r'^blog/', include('mysite.myapp.blog.urls')),)urlpatterns += patterns('',    url(r'^guestbook/', include('mysite.myapp.guestbook.urls')),)urlpatterns += patterns('',    url(r'^catalog/', include('mysite.myapp.catalog.urls')),)##blog/urls.pyurlpatterns = patterns('mysite.myapp.blog.views',    url(r'^new/$', 'new_post'),    url(r'^topics/(?P<topic_name>/w+)/new/$', 'new_post')),)##guestbook/urls.pyurlpatterns = patterns('mysite.myapp.guestbook.views',    url(r'^$', 'index'),    url(r'^add/$', 'new_entry')),)##catalog/urls.pyurlpatterns = patterns('mysite.myapp.catalog.views',    url(r'^$', 'index'),)

這樣一來,好處多多:

  • 避免在URL定義里重復輸入blog guestbook catalog

1.5 函數對象 v.s. 函數名字符串

函數名字符串說的是url()方法的第二個參數, 如'index', 'new_entry'
Django不光允許你用函數名字符串,還允許用“函數對象”

from django.conf.urls.defaults import *from mysite.myapp import viewsurlpatterns = patterns('',   url(r'^$', views.index),   url(...),)

到此為止,URL部分解決的是什么問題? -- 如何設置URL定義以及如何將URL和視圖(視圖函數)聯系起來

下面看看這些視圖函數的周圍都有些什么

2 HTTP建模:請求、響應和中間件

Django把HTTP歸結為簡單的Python請求對象+響應對象(這點跟Yii2很像哦)

加上URL轉發和視圖函數,一個請求在你的Web應用程序中的流程如下:

  • web服務器接到一個HTTP請求
  • Django把請求轉換成“請求對象”
  • Django在URLconf里查找正確的視圖函數
  • 調用這個視圖函數,參數為請求對象以及任何捕捉到的URL參數
  • 視圖會創建并返回一個“響應對象”
  • Django將這個響應對象轉換成Web服務器可以理解的格式
  • Web服務器將響應返回給客戶端

下面說說思路,先看看請求對象和響應對象,以及他們的組件,然后深入Django中間件,這個中間件提供了進入上述過程中多個步驟的接口

2.1 請求對象

所有視圖函數都接受一個“請求”參數HttPRequest對象,這是一組經過良好封裝的屬性,代表了從Web服務器傳遞進來的原始HTTP請求。
其中最常用的屬性是請求數據是GET和POST數據結構。

2.1.1 GET和POST字典

這個GET和POST數據結構一Python字典的形式出現,即 request.GET request.POST (雖然結構相同,但是填充方法很不一樣)
他們一起為參數化Web請求提供了一個靈活的方式。

例如:請求URL為/userlist/?page=2對應的處理為:

def userlist(request):    return paginated_userlist_page(page=request.GET['page'])

同理,還有request.POSTrequest.REQUEST(不常用,因為pythonic哲學建議“盡可能顯式表達意思而不要依賴于默認行為”

2.1.2 Cookies和Sessions

請求對象里接下來最常用的是request.COOKIES,也是一個字典,代表了存儲在用戶瀏覽器中的HTTP Cookies

通長,cookies使用支持會話session的

Django里的會話也是HttpRequest對象的一個字典類屬性,注意,這里request.session的session是小寫,因為session并不是HTTP協議的一部分

2.1.3 其他服務器變量

  • path -- URL中域名后的部分,通常也是URLconf要處理的字符串
  • method -- 標明請求用的是哪一個HTTP請求方法
  • encoding -- 表明了用來解碼表單提交數據所需的編碼字符集的字符串
  • FILES --字典對象,包含所有上傳的文件,每一個值又是一個字典,包含了文件名、內容類型以及文件內容
  • META --字典對象,包含了其他的變量,如CONTENT_LENGTH,HTTP_REFERER,REMOTE_ADDR,SERVER_NAME
  • user -- Django的認證用戶,只有當你的站點激活了Django認證機制才會有
  • raw_post_data -- 建議直接用 request.POST

2.2 響應對象

響應要比請求簡單,其主要數據就是存在content屬性里的正文,一般而言就是一個大大的HTML字符串

response = HttpResponse("<html>this is a tiny web page</html>")response = HttpResponse()response.write("<html>")response.write("this is a tiny web page")response.write("</html>")response["Content-Type"] = "text/csv"response["Content-Length"] = 256

2.3 中間件

看來,Django的基本流程還是簡單的,接受請求-找到合適的視圖函數-返回響應,不過還可以在上面加諸更多層次(中間件)來讓其更靈活強大
中間件 middleware 可以在多個地方改變輸入和輸出

  • 改變輸入 -- 在請求到達視圖之前, 如process_request
  • 改變輸出 -- 修改視圖創建的響應, 如process_view

在settings.py文件里的MIDDLEWARE_CLASSES元組中列出后,Django會內省這些類并且在適當的時候調用其方法。
有些類則需要特定的"contrib."應用程序支持,比如認證框架

2.3.1 請求中間件

請求中間件用在輸入端,定義為一個實現了process_request方法的類,

此方法接受request作為參數,返回一個HttpResponse或者子類的對象,或者返回None(Django繼續處理其他請求中間件)

from some_exterior_auth_lib import get_userclass ExteriorAuthMiddleware(object):    def process_request(self, request):        token = request.COOKIES.get('auth_token')        if token is None and not request.path.startswith('/login')            return HttpResponseRedirect('/login')        request.exterior_user = get_user(token)

這個例子中,請求中間件給請求對象添加了額外屬性request.exterior_user,添加了之后,process_request隱含返回None(如果沒有顯式的return語句,python函數一定返回None);然后Django會繼續處理其他請求中間件,最后才輪到視圖函數本身

如果,token無效的話,中間件會把用戶redirect到登陸頁,因為是請求中間件,重定向之后的所有代碼都會忽略掉不執行。

可見,請求中間件有2個特性,給請求對象添加額外屬性+返回一個立刻發送給請求客戶端的HttpResponse(或子類)對象,之后代碼忽略

2.3.2 響應中間件

響應中間件運行在視圖函數返回的HttpResponse對象之上,實現一個process_response方法

此方法接受request和response兩個參數,返回一個HttpResponse或者子類的對象

class TextFilterMiddleware(object):    def process_response(self, request, response):        response["Content-Type"] = "text/csv"        response.content = response.content.replace('foo', 'bar')

可見,響應中間件主要作用是在響應里插入額外的頭信息,或者處理響應內容

3 視圖與邏輯

因為之前我熟悉的是php的Yii框架,那里的視圖概念跟Django這里的完全不是一碼事

這里的視圖也叫控制器!!!是Django的核心,提供了幾乎所有的實際的程序邏輯

在定義和使用models的時候,我們是數據庫管理員
在編寫template的時候,我們是界面設計師
在編寫views視圖的時候,我們才是真正的軟件工程師

3.1 就是Python函數

簡單說,在Python中,視圖就是函數

唯一要求是:這個函數接受一個HttpRequest對象并返回一個HttpResponse對象,另外在URLconf中的正則模式中定義命名組(named group)和可選的字典參數作為該函數的參數,舉例:

urlpatterns = patterns('mysite.myapp.views',    url(r'^archives/(?P<year>/d{4})/(?P<month>/d{2})/(?P<day>/d{2})/$'),    'archive',    {'show_private': True},)from django.http import HttpResponsedef archive(request, year, month, day, show_private):   return HttpResponse()

3.2 通用視圖

通用視圖一般都提供了很多選項,有些是某個視圖特有的,但是其它都是全局的,比如:

  • template_name - 允許用戶重寫視圖模板位置
  • extra_context - 字典,允許用戶向模板context傳遞額外的信息 (具體細節看下一節06節)

通用視圖都是組成一個兩層的模塊層次:

  • simple.direct_to_template
  • list_detail.object_list 和 list_detail.object_detail
  • create_updata.create_object 和 create_update.update_object
  • data_based.*

使用通用視圖,用戶只需要在URLconf文件里引用它們,傳遞適合的參數,并確保視圖要渲染和返回的模板存在即可:

from django.views.generic.list_detail import object_detailfrom django.confi.urls.defaults import *from mysite.myapp.models import Personurlpatterns = patterns('',    url(r'^people/(?P<object_id>/d+)/$', object_detail, {        'queryset' : Person.objects.all()    }))

這個例子中,定義了一個正則匹配 /people/25/ 這樣的URL
用到的通用視圖 object_detail 需要兩個參數,分別是 object_id 和 一個 QuerySet,分別從URL參數和字典參數提供。

3.3 半通用視圖

上面例子中 queryset 不光可以是 Person.objects.all(), 也可以是 Person.objects.filter(is_employee=True),
但是,不能是 Person.objects.filter(id=object_id)

這是 URLconf自身固有的限制,你不能在正則表達式解析之前對撲捉到的URL參數進行任何操作,那怎么辦呢?

半通用視圖可以完美解決這個問題,將 對通用視圖和數據模型的部分從urls.py中摘出去放在視圖文件中

## urls.pyfrom django.conf.urls.defaults iimport *urlpatterns = patterns('mysite.myapp.views',    url(r'^people/by_lastname/(?P<last_name>/w+)/$', 'last_name_search'),)## view.pyfrom django.views.generic.list_detail import object_listfrom mysite.myapp.models import Person def last_name_search(request, last_name):    return object_list(request,        queryset = Person.objects.filter(last__istartswith=last_name)    }

如何?完美解決了這個問題吧

雖然函數接受了一個在URL正則中命名組里定義的last_name參數,但是還是把99%的工作給了通用視圖,之所以可以這樣,就是因為通用視圖就是普通Python函數,一樣可以導入和調用

http://m.survivalescaperooms.com/ganiks/p/django-url-http-mechnism-and-views.html

3.4 自定義視圖

上面兩種都離不開通用視圖,但有時候就是沒法用通用視圖

一旦自定義視圖,Django基本上就不再對你做任何限制了,但是它還是提供了一些捷徑給你,其中大多數都屬于django.shotcuts模塊

  • render_to_response
  • Http404 -- 定義在djaong.http模塊下,是Exception子類,會返回一個HTTP 404錯誤碼并渲染一個頂層的404.html模板
  • get_object_or_404, get_list_or_404 -- 就是將兩步合一
from django.shortcuts import render_to_responsefrom django.http import Http404from mysite.myapp.models import Persondef person_detail(request, id):    try:        person = Person.objects.get(pk=id)    except Person.DoesNotExist:        raise Http404    return return_to_response("person/detail.html", {"person":person})

第二種寫法會簡捷很多

from django.shotcuts import render_to_response, get_object_or_404from mysite.myapp.models import Persondef person_detail(request, id):    person = get_object_or_404(Person, pk=id)    return render_to_response("person/detail.html", {"person":person})

以后在定義視圖的過程中,你會發現更喜歡用args/kwargs的方式,因為它們可以接受任何位置參數和關鍵字參數,靈活快捷,你不用再回到URLconf中去記住你是怎么捕捉正則參數或是關鍵字參數命名了。

def myview(*args, **kwargs):    # ... args[0]    # ... kwargs['object_id']

http://m.survivalescaperooms.com/ganiks/p/django-url-http-mechnism-and-views.html

本節完,下一節關于模板渲染網頁以及表單和表單驗證。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 惠州市| 武强县| 鹿邑县| 虹口区| 天等县| 石城县| 乌拉特后旗| 庐江县| 饶阳县| 镇坪县| 芜湖县| 沂水县| 察雅县| 苏尼特右旗| 会昌县| 临汾市| 博兴县| 当雄县| 上栗县| 武陟县| 邵阳县| 奎屯市| 吴桥县| 南雄市| 麻城市| 崇仁县| 深州市| 浦北县| 犍为县| 池州市| 沾益县| 同江市| 裕民县| 磴口县| 宜章县| 白城市| 和田市| 班戈县| 苗栗县| 泽州县| 酉阳|