天天看點

python get argument_Python-Web架構-get_argument方法

Python-Web架構-get_argument方法

目錄概覽

1.使用get_argument擷取url query參數

2.為何get_argument不區分POST與GET?

3.get_argument傳回unicode資料類型的問題

1.使用get_argument擷取url query參數

Tornado的每個請求處理程式,我們叫做handler,handler裡可以自定義自己的處理程式,其實也就是重寫方法,如post,get,get_current_user,send_error等等,這裡我們隻講get和post的自定義。

我們都知道,在Tornado裡,獲得使用者的輸入,都是一個get_argument搞定,似乎很順理成章:

def post(self):

nowamagic = self.get_argument('nowamagic')

self.write( nowamagic )

import urlparse

urlparse.urlparse('http://www.nowamagic.net/academy/detail/13321002?page=1#comment')

ParseResult(scheme='http', netloc='www.nowamagic.net', path='/academy/detail/13321002', params='', query='page=1', fragment='comment')

url由scheme(協定),netloc(主機),path(路徑),params(最後路徑的參數),query(查詢字段),fragment(錨)組成。

下面我們要擷取URL裡的GET參數,也就是擷取url query中的參數,怎麼辦呢?

對于單一的值,在get和post中調用self.get_argument("name", "default")。

對于多選的值,調用self.get_arguments("name")即可。

get_argument方法可以設定預設值,也可以設定是否删除兩端的空格。

源碼聲明如下:

get_argument(self, name, default=_ARG_DEFAULT, strip=True)

get_arguments(self, name, strip=True)

2.為何get_argument不區分POST與GET?

Tornado的get_argument有點類似PHP的 $ _REQUEST,是不區分GET與POST的。而且Tornado好像是沒有PHP裡的$ _GET,$ _POST這樣的區分擷取get資料與post資料的方法。為什麼會這樣麼?

URL的query string還是x-www-form-encode的資料可以按key/value方式來解析,其實是一種約定俗成的規矩。甚至表單POST的編碼格式都是和GET的query string編碼是一樣的。CGI的實作中也隻用了一套代碼來處理。就說兩種方法實際上在做同一件事情。

而同時提供key/value的query string和x-www-form-encode的POST資料,也不違反任何協定和标準。

其次,通常當你要送出key/value資料的時候,目的是一緻的。POST隻不過允許你送出更多的資料而已。為什麼要混用兩套東西呢?

tornado做的,隻不過是提供接口提高最常見場景的編碼效率。如果應用場景比較特殊,可以自行解析request.body, request.url,擷取原始的資料進行處理。

從安全角度來說,在Tornado中,一個RequestHandler中,處理GET和POST是兩個不同的函數,這是一個很關鍵的因素。

對于某些Framework(比如Zend Framework),Model不區分GET和POST方法,換句話說,一個URL Patten不管是通過POST還是GET來通路,處理函數都是同一個,是以Zend的getParam方法就向程式員提供了資料來源的選擇。而且這對于Zend Framework程式的安全也是至關重要。

對于GET請求,沒什麼好說的,因為GET請求的資料來源隻有query string一條路,是以指定資料來源是沒有意義的。

對于POST請求,XSRF攻擊者的确可以将本來應該寫在x-www-form-encode裡的資料轉移到query string裡,但是這麼做毫無意義。因為這樣做會使請求變為get函數來處理。攻擊自然會失敗。

是以,Tornado的這種做法是有道理的,而不是簡單的為了提高編碼效率。畢竟,編碼效率的提高也必須建立在保證安全的基礎上。

3. get_argument傳回unicode資料類型的問題

在 Tornado 裡,self.get_argument傳回的資料類型為unicode:

chars = self.get_argument('chars')

self.write( str(type(chars)) )

# 輸出

#

get_argument在擷取資料的時候,會進行decode("utf-8")操作,因為get_argument最終調用了tornado.escape下面的to_unicode方法,也就是argument會通過decode("utf-8")來轉成unicode:

def to_unicode(value):

"""

Converts a string argument to a unicode string.

If the argument is already a unicode string or None, it is returned

unchanged. Otherwise it must be a byte string and is decoded as utf8.

"""

if isinstance(value, _TO_UNICODE_TYPES):

return value

assert isinstance(value, bytes)

return value.decode("utf-8")

# to_unicode was previously named _unicode not because it was private,

# but to avoid conflicts with the built-in unicode() function/type

_unicode = to_unicode

get_argument擷取資料之後一般需要先使用u.encode('utf-8')轉換成string類型後才能使用。

如果用get_argument無法擷取資料,可以用更加原始的方法通過self.request.arguments擷取GET或者POST的所有參數字典,這個字典是未經過decode處理的原生參數,每個參數都是字典裡面的一項,主要每個參數對應的項都是一個清單。