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 )
先介绍一点基本知识。我们来看看这么一个URL:http://www.nowamagic.net/academy/detail/13321002?page=1#comment
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)) )
# 输出
# <type 'unicode'>
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处理的原生参数,每个参数都是字典里面的一项,主要每个参数对应的项都是一个列表。
©哈尔滨商业大学 银河统计工作室
银河统计工作室成员由在校统计、计算机部分师生和企业数据数据分析师组成,维护和开发银河统计网和银河统计博客(技术文档)。专注于数据挖掘技术研究和运用,探索统计学、应用数学和IT技术有机结合,尝试大数据条件下新型统计学教学模式。