Django中URL視圖函數(shù)的一些高級概念介紹
說到關于請求方法的分支,讓我們來看一下可以用什么好的方法來實現(xiàn)它。 考慮這個 URLconf/view 設計:
# urls.py from django.conf.urls.defaults import * from mysite import views urlpatterns = patterns('', # ... (r'^somepage/$', views.some_page), # ... ) # views.py from django.http import Http404, HttpResponseRedirect from django.shortcuts import render_to_response def some_page(request): if request.method == 'POST': do_something_for_post() return HttpResponseRedirect('/someurl/') elif request.method == 'GET': do_something_for_get() return render_to_response('page.html') else: raise Http404()
在這個示例中,`` some_page()`` 視圖函數(shù)對`` POST`` 和`` GET`` 這兩種請求方法的處理完全不同。 它們唯一的共同點是共享一個URL地址: `` /somepage/.``正如大家所看到的,在同一個視圖函數(shù)中對`` POST`` 和`` GET`` 進行處理是一種很初級也很粗糙的做法。 一個比較好的設計習慣應該是,用兩個分開的視圖函數(shù)——一個處理`` POST`` 請求,另一個處理`` GET`` 請求,然后在相應的地方分別進行調用。
我們可以像這樣做:先寫一個視圖函數(shù)然后由它來具體分派其它的視圖,在之前或之后可以執(zhí)行一些我們自定的程序邏輯。 下邊的示例展示了這個技術是如何幫我們改進前邊那個簡單的`` some_page()`` 視圖的:
# views.py from django.http import Http404, HttpResponseRedirect from django.shortcuts import render_to_response def method_splitter(request, GET=None, POST=None): if request.method == 'GET' and GET is not None: return GET(request) elif request.method == 'POST' and POST is not None: return POST(request) raise Http404 def some_page_get(request): assert request.method == 'GET' do_something_for_get() return render_to_response('page.html') def some_page_post(request): assert request.method == 'POST' do_something_for_post() return HttpResponseRedirect('/someurl/') # urls.py from django.conf.urls.defaults import * from mysite import views urlpatterns = patterns('', # ... (r'^somepage/$', views.method_splitter, {'GET': views.some_page_get, 'POST': views.some_page_post}), # ... )
讓我們從頭看一下代碼是如何工作的:
我們寫了一個新的視圖,`` method_splitter()`` ,它根據(jù)`` request.method`` 返回的值來調用相應的視圖??梢钥吹剿鼛в袃蓚€關鍵參數(shù),`` GET`` 和`` POST`` ,也許應該是* 視圖函數(shù)* 。如果`` request.method`` 返回`` GET`` ,那它就會自動調用`` GET`` 視圖。 如果`` request.method`` 返回的是`` POST`` ,那它調用的就是`` POST`` 視圖。 如果`` request.method`` 返回的是其它值(如:`` HEAD`` ),或者是沒有把`` GET`` 或`` POST`` 提交給此函數(shù),那它就會拋出一個`` Http404`` 錯誤。
在URLconf中,我們把`` /somepage/`` 指到`` method_splitter()`` 函數(shù),并把視圖函數(shù)額外需要用到的`` GET`` 和`` POST`` 參數(shù)傳遞給它。
最終,我們把`` some_page()`` 視圖分解到兩個視圖函數(shù)中`` some_page_get()`` 和`` some_page_post()`` 。這比把所有邏輯都擠到一個單一視圖的做法要優(yōu)雅得多。
注意,在技術上這些視圖函數(shù)就不用再去檢查`` request.method`` 了,因為`` method_splitter()`` 已經(jīng)替它們做了。 (比如,`` some_page_post()`` 被調用的時候,我們可以確信`` request.method`` 返回的值是`` post`` 。)當然,這樣做不止更安全也能更好的將代碼文檔化,這里我們做了一個假定,就是`` request.method`` 能象我們所期望的那樣工作。
現(xiàn)在我們就擁有了一個不錯的,可以通用的視圖函數(shù)了,里邊封裝著由`` request.method`` 的返回值來分派不同的視圖的程序。關于`` method_splitter()`` 就不說什么了,當然,我們可以把它們重用到其它項目中。
然而,當我們做到這一步時,我們仍然可以改進`` method_splitter`` 。從代碼我們可以看到,它假設`` Get`` 和`` POST`` 視圖除了`` request`` 之外不需要任何其他的參數(shù)。那么,假如我們想要使用`` method_splitter`` 與那種會從URL里捕捉字符,或者會接收一些可選參數(shù)的視圖一起工作時該怎么辦呢?
為了實現(xiàn)這個,我們可以使用Python中一個優(yōu)雅的特性 帶星號的可變參數(shù) 我們先展示這些例子,接著再進行解釋
def method_splitter(request, *args, **kwargs): get_view = kwargs.pop('GET', None) post_view = kwargs.pop('POST', None) if request.method == 'GET' and get_view is not None: return get_view(request, *args, **kwargs) elif request.method == 'POST' and post_view is not None: return post_view(request, *args, **kwargs) raise Http404
這里,我們重構method_splitter(),去掉了GET和POST兩個關鍵字參數(shù),改而支持使用*args和和**kwargs(注意*號) 這是一個Python特性,允許函數(shù)接受動態(tài)的、可變數(shù)量的、參數(shù)名只在運行時可知的參數(shù)。 如果你在函數(shù)定義時,只在參數(shù)前面加一個*號,所有傳遞給函數(shù)的參數(shù)將會保存為一個元組. 如果你在函數(shù)定義時,在參數(shù)前面加兩個*號,所有傳遞給函數(shù)的關鍵字參數(shù),將會保存為一個字典
例如,對于這個函數(shù)
def foo(*args, **kwargs): print "Positional arguments are:" print args print "Keyword arguments are:" print kwargs
看一下它是怎么工作的
>>> foo(1, 2, 3) Positional arguments are: (1, 2, 3) Keyword arguments are: {} >>> foo(1, 2, name='Adrian', framework='Django') Positional arguments are: (1, 2) Keyword arguments are: {'framework': 'Django', 'name': 'Adrian'}
回過頭來看,你能發(fā)現(xiàn)我們用method_splitter()和*args接受**kwargs函數(shù)參數(shù)并把它們傳遞到正確的視圖。any 但是在我們這樣做之前,我們要調用兩次獲得參數(shù)kwargs.pop()GETPOST,如果它們合法的話。 (我們通過指定pop的缺省值為None,來避免由于一個或者多個關鍵字缺失帶來的KeyError)
相關文章
Python使用matplotlib實現(xiàn)基礎繪圖功能示例
這篇文章主要介紹了Python使用matplotlib實現(xiàn)基礎繪圖功能,結合實例形式分析了Python基于matplotlib實現(xiàn)正弦、余弦圖形及多軸圖的相關繪制操作技巧,需要的朋友可以參考下2018-07-07python實現(xiàn)對excel表中的某列數(shù)據(jù)進行排序的代碼示例
這篇文章主要給大家介紹了如何使用python實現(xiàn)對excel表中的某列數(shù)據(jù)進行排序,文中有相關的代碼示例供大家參考,具有一定的參考價值,需要的朋友可以參考下2023-11-11python格式化輸出保留2位小數(shù)的實現(xiàn)方法
這篇文章主要介紹了python格式化輸出保留2位小數(shù)的實現(xiàn)方法,需要的朋友可以參考下2019-07-07windows下安裝Python虛擬環(huán)境virtualenvwrapper-win
這篇文章主要介紹了windows下安裝Python虛擬環(huán)境virtualenvwrapper-win,內容超簡單,非常不錯,具有一定的參考借鑒價值,需要的朋友可以參考下2019-06-06解決pycharm中導入自己寫的.py函數(shù)出錯問題
今天小編就為大家分享一篇解決pycharm中導入自己寫的.py函數(shù)出錯問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-02-02