(2018-05-26.Python從Zero到One)8、(Tornado)深入tornado__1.3.2 輸入

3.2 輸入

下面幾節(jié)主要講解tornado.web.RequestHandler。

回想一下,利用HTTP協(xié)議向服務(wù)器傳參有幾種途徑?

  • 查詢字符串(query string),形如key1=value1&key2=value2;
  • 請(qǐng)求體(body)中發(fā)送的數(shù)據(jù),比如表單數(shù)據(jù)、json、xml;
  • 提取uri的特定部分,如/blogs/2016/09/0001,可以在服務(wù)器端的路由中用正則表達(dá)式截??;
  • 在http報(bào)文的頭(header)中增加自定義字段,如X-XSRFToken=itcast。

我們現(xiàn)在來看下tornado中為我們提供了哪些方法來獲取請(qǐng)求的信息。

1. 獲取查詢字符串參數(shù)

get_query_argument(name, default=_ARG_DEFAULT, strip=True)

從請(qǐng)求的查詢字符串中返回指定參數(shù)name的值,如果出現(xiàn)多個(gè)同名參數(shù),則返回最后一個(gè)的值。

default為設(shè)值未傳name參數(shù)時(shí)返回的默認(rèn)值,如若default也未設(shè)置,則會(huì)拋出tornado.web.MissingArgumentError異常。

strip表示是否過濾掉左右兩邊的空白字符,默認(rèn)為過濾。

get_query_arguments(name, strip=True)

從請(qǐng)求的查詢字符串中返回指定參數(shù)name的值,注意返回的是list列表(即使對(duì)應(yīng)name參數(shù)只有一個(gè)值)。若未找到name參數(shù),則返回空列表[]。

strip同前,不再贅述。

2. 獲取請(qǐng)求體參數(shù)

get_body_argument(name, default=_ARG_DEFAULT, strip=True)

從請(qǐng)求體中返回指定參數(shù)name的值,如果出現(xiàn)多個(gè)同名參數(shù),則返回最后一個(gè)的值。

default與strip同前,不再贅述。

get_body_arguments(name, strip=True)

從請(qǐng)求體中返回指定參數(shù)name的值,注意返回的是list列表(即使對(duì)應(yīng)name參數(shù)只有一個(gè)值)。若未找到name參數(shù),則返回空列表[]。

strip同前,不再贅述。

說明

對(duì)于請(qǐng)求體中的數(shù)據(jù)要求為字符串,且格式為表單編碼格式(與url中的請(qǐng)求字符串格式相同),即key1=value1&key2=value2,HTTP報(bào)文頭Header中的"Content-Type"為application/x-www-form-urlencoded 或 multipart/form-data。對(duì)于請(qǐng)求體數(shù)據(jù)為json或xml的,無法通過這兩個(gè)方法獲取。

3. 前兩類方法的整合

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

從請(qǐng)求體和查詢字符串中返回指定參數(shù)name的值,如果出現(xiàn)多個(gè)同名參數(shù),則返回最后一個(gè)的值。

default與strip同前,不再贅述。

get_arguments(name, strip=True)

從請(qǐng)求體和查詢字符串中返回指定參數(shù)name的值,注意返回的是list列表(即使對(duì)應(yīng)name參數(shù)只有一個(gè)值)。若未找到name參數(shù),則返回空列表[]。

strip同前,不再贅述。

說明

對(duì)于請(qǐng)求體中數(shù)據(jù)的要求同前。 這兩個(gè)方法最常用。

用代碼來看上述六中方法的使用:

# coding:utf-8

import tornado.web
import tornado.ioloop
import tornado.httpserver
import tornado.options
from tornado.options import options, define
from tornado.web import RequestHandler, MissingArgumentError

define("port", default=8000, type=int, help="run server on the given port.")

class IndexHandler(RequestHandler):
    def post(self):
        query_arg = self.get_query_argument("a")
        query_args = self.get_query_arguments("a")
        body_arg = self.get_body_argument("a")
        body_args = self.get_body_arguments("a", strip=False)
        arg = self.get_argument("a")
        args = self.get_arguments("a")

        default_arg = self.get_argument("b", "itcast")
        default_args = self.get_arguments("b")

        try:
            missing_arg = self.get_argument("c")
        except MissingArgumentError as e:
            missing_arg = "We catched the MissingArgumentError!"
            print e
        missing_args = self.get_arguments("c")

        rep = "query_arg:%s<br/>" % query_arg
        rep += "query_args:%s<br/>" % query_args 
        rep += "body_arg:%s<br/>"  % body_arg
        rep += "body_args:%s<br/>" % body_args
        rep += "arg:%s<br/>"  % arg
        rep += "args:%s<br/>" % args 
        rep += "default_arg:%s<br/>" % default_arg 
        rep += "default_args:%s<br/>" % default_args 
        rep += "missing_arg:%s<br/>" % missing_arg
        rep += "missing_args:%s<br/>" % missing_args

        self.write(rep)

if __name__ == "__main__":
    tornado.options.parse_command_line()
    app = tornado.web.Application([
        (r"/", IndexHandler),
    ])
    http_server = tornado.httpserver.HTTPServer(app)
    http_server.listen(options.port)
    tornado.ioloop.IOLoop.current().start()

day60_tornado-深入tornado-01.png

注意:以上方法返回的都是unicode字符串

思考

  1. 什么時(shí)候設(shè)置default,什么時(shí)候不設(shè)置default?
  2. default的默認(rèn)值_ARG_DEFAULT是什么?
  3. 什么時(shí)候使用strip,亦即什么時(shí)候要截?cái)嗫瞻鬃址?,什么時(shí)候不需要?

4. 關(guān)于請(qǐng)求的其他信息

RequestHandler.request 對(duì)象存儲(chǔ)了關(guān)于請(qǐng)求的相關(guān)信息,具體屬性有:

  • method HTTP的請(qǐng)求方式,如GET或POST;

  • host 被請(qǐng)求的主機(jī)名;

  • uri 請(qǐng)求的完整資源標(biāo)示,包括路徑和查詢字符串;

  • path 請(qǐng)求的路徑部分;

  • query 請(qǐng)求的查詢字符串部分;

  • version 使用的HTTP版本;

  • headers 請(qǐng)求的協(xié)議頭,是類字典型的對(duì)象,支持關(guān)鍵字索引的方式獲取特定協(xié)議頭信息,例如:request.headers["Content-Type"]

  • body 請(qǐng)求體數(shù)據(jù);

  • remote_ip 客戶端的IP地址;

  • files 用戶上傳的文件,為字典類型,型如:

    {
      "form_filename1":[<tornado.httputil.HTTPFile>, <tornado.httputil.HTTPFile>],
      "form_filename2":[<tornado.httputil.HTTPFile>,],
      ... 
    }
    
    

    tornado.httputil.HTTPFile是接收到的文件對(duì)象,它有三個(gè)屬性:

    • filename 文件的實(shí)際名字,與form_filename1不同,字典中的鍵名代表的是表單對(duì)應(yīng)項(xiàng)的名字;
    • body 文件的數(shù)據(jù)實(shí)體;
    • content_type 文件的類型。 這三個(gè)對(duì)象屬性可以像字典一樣支持關(guān)鍵字索引,如request.files["form_filename1"][0]["body"]。

我們來實(shí)現(xiàn)一個(gè)上傳文件并保存在服務(wù)器本地的小程序upload.py:

# coding:utf-8

import tornado.web
import tornado.ioloop
import tornado.httpserver
import tornado.options
from tornado.options import options, define
from tornado.web import RequestHandler

define("port", default=8000, type=int, help="run server on the given port.")

class IndexHandler(RequestHandler):
    def get(self):
        self.write("hello itcast.")

class UploadHandler(RequestHandler): 
    def post(self):
        files = self.request.files
        img_files = files.get('img')
        if img_files:
            img_file = img_files[0]["body"]
            file = open("./itcast", 'w+')
            file.write(img_file)
            file.close()
        self.write("OK")

if __name__ == "__main__":
    tornado.options.parse_command_line()
    app = tornado.web.Application([
        (r"/", IndexHandler),
        (r"/upload", UploadHandler),
    ])
    http_server = tornado.httpserver.HTTPServer(app)
    http_server.listen(options.port)
    tornado.ioloop.IOLoop.current().start()

day60_tornado-深入tornado-02.png
day60_tornado-深入tornado-03.png

5. 正則提取uri

tornado中對(duì)于路由映射也支持正則提取uri,提取出來的參數(shù)會(huì)作為RequestHandler中對(duì)應(yīng)請(qǐng)求方式的成員方法參數(shù)。若在正則表達(dá)式中定義了名字,則參數(shù)按名傳遞;若未定義名字,則參數(shù)按順序傳遞。提取出來的參數(shù)會(huì)作為對(duì)應(yīng)請(qǐng)求方式的成員方法的參數(shù)。

# coding:utf-8

import tornado.web
import tornado.ioloop
import tornado.httpserver
import tornado.options
from tornado.options import options, define
from tornado.web import RequestHandler

define("port", default=8000, type=int, help="run server on the given port.")

class IndexHandler(RequestHandler):
    def get(self):
        self.write("hello itcast.")

class SubjectCityHandler(RequestHandler):
    def get(self, subject, city):
        self.write(("Subject: %s<br/>City: %s" % (subject, city)))

class SubjectDateHandler(RequestHandler):
    def get(self, date, subject):
        self.write(("Date: %s<br/>Subject: %s" % (date, subject)))

if __name__ == "__main__":
    tornado.options.parse_command_line()
    app = tornado.web.Application([
        (r"/", IndexHandler),
        (r"/sub-city/(.+)/([a-z]+)", SubjectCityHandler), # 無名方式
        (r"/sub-date/(?P<subject>.+)/(?P<date>\d+)", SubjectDateHandler), # 命名方式
    ])
    http_server = tornado.httpserver.HTTPServer(app)
    http_server.listen(options.port)
    tornado.ioloop.IOLoop.current().start()

day60_tornado-深入tornado-04.png
day60_tornado-深入tornado-05.png

建議:提取多個(gè)值時(shí)最好用命名方式。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 引言 以Django為代表的python web應(yīng)用部署時(shí)采用wsgi協(xié)議與服務(wù)器對(duì)接(被服務(wù)器托管),而這類服務(wù)...
    大熊_7d48閱讀 2,130評(píng)論 0 3
  • 譯者說 Tornado 4.3于2015年11月6日發(fā)布,該版本正式支持Python3.5的async/await...
    TaoBeier閱讀 3,184評(píng)論 0 10
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,680評(píng)論 19 139
  • RequestHandler 1,利用HTTP協(xié)議向服務(wù)器傳參幾種途徑 1,查詢字符串(query string)...
    曉可加油閱讀 1,517評(píng)論 0 0
  • 之前看到有樓主發(fā)了一條這樣的梗,小女子閑來無事,借著這個(gè)梗也抒發(fā)一下個(gè)人的想法,無意冒犯前人,只是單純的抒發(fā)一下,...
    西里陽光閱讀 1,251評(píng)論 0 2

友情鏈接更多精彩內(nèi)容