tornado框架相比Django这样的“重武器”轻便了很多,这也意味着tornado没有像Django那样有很多封装好的方法供我们使用,在处理前端请求的数据也是如此。

  本文总结一下tornado框架处理前端传来的RequestPayload与FormData两种格式的数据的方法,因为现在很少有人传Query String Parameters这种类型的数据了,所以就不介绍了。

  Query String Parameters

  当发起一次GET请求时,参数会以url string的形式进行传递。即后的字符串则为其请求参数,并以作为分隔符。

  如下http请求报文头:

  // General

  Request URL: http://foo.com?x=1&y=2

  Request Method: GET

  // Query String Parameters

  x=1&y=2

  Form Data

  当发起一次POST请求时,若未指定content-type,则默认content-type为application/x-www-form-urlencoded。即参数会以Form Data的形式进行传递,不会显式出现在请求url中。

  如下http请求报头:

  // General

  Request URL: http://foo.com

  Request Method: POST

  // Request Headers

  content-type: application/x-www-form-urlencoded; charset=UTF-8

  // Form Data

  x=1&y=2

  Request Payload

  当发起一次POST请求时,若content-type为application/json,则参数会以Request Payload的形式进行传递(显然的,数据格式为JSON),不会显式出现在请求url中。

  如下http请求报头:

  / General

  Request URL: http://foo.com

  Request Method: POST

  / Request Headers

  content-type: application/json; charset=UTF-8

  // Request Payload

  x=1&y=2

  ajax请求可以设置content-type请求头!

  前端的请求如下:

Index

  title:

  author:

  

  $('#button').click(function () {

  title =$("#t1").val();

  author =$("#a1").val();

  // console.log(title, author);

  $.ajax({

  url: '/index',

  type: 'POST',

  contentType: 'application/json', //设置请求头,注明编码格式

  data: JSON.stringify({"title": title, "author": author}), // 注意得先序列化才能传递

  success: function (data) {

  console.log(data);

  }

  })

  });

  后端tornado代码如下:

  # -*- coding:utf-8 -*-

  import json

  import os.path

  import tornado.locale

  import tornado.httpserver

  import tornado.ioloop

  import tornado.options

  import tornado.web

  from tornado.options import define, options

  from logics import handle_payload_args

  define("port", default=8006, help="run on the given port", type=int)

  class Application(tornado.web.Application):

  def __init__(self):

  handlers = [

  # 主页

  (r"/index", MainHandler),

  ]

  settings = dict(

  template_path=os.path.join(os.path.dirname(__file__),"templates"),

  static_path=os.path.join(os.path.dirname(__file__),"static"),

  debug=True,

  )

  # 执行父类__init__方法

  tornado.web.Application.__init__(self, handlers,**settings)

  from tornado.escape import json_decode

  class MainHandler(tornado.web.RequestHandler):

  def get(self):

  self.render(

  "index.html",

  )

  def post(self):

  ret=self.request.body # 二进制

  print("request.body:",ret,type(ret)) # request.body: b''

  req= json_decode(ret) # 直接用json_decode就可以

  print("req:",req,type(req)) # req: {'title': '222', 'author': '123'}

  result=json.dumps(req,ensure_ascii=False) # 设置ensure_ascii=False,防止中文乱码

  self.write(result)

  if __name__=="__main__":

  tornado.options.parse_command_line()

  http_server = tornado.httpserver.HTTPServer(Application())

  http_server.listen(options.port)

  tornado.ioloop.IOLoop.instance().start()

  页面调试效果

  

  前端可以用form表单模拟传递数据:

Index

  title:

  author:

  tornado没有Django封装的POST属性,需要通过get_argument方法一个个获取,太麻烦,可以写一个方法封装一下:

  # -*- coding:utf-8 -*-

  import json

  import os.path

  import tornado.locale

  import tornado.httpserver

  import tornado.ioloop

  import tornado.options

  import tornado.web

  from tornado.options import define, options

  define("port", default=8006, help="run on the given port", type=int)

  class Application(tornado.web.Application):

  def __init__(self):

  handlers = [

  # 主页

  (r"/index", MainHandler),

  ]

  settings = dict(

  template_path=os.path.join(os.path.dirname(__file__),"templates"),

  static_path=os.path.join(os.path.dirname(__file__),"static"),

  debug=True,

  )

  # 执行父类__init__方法

  tornado.web.Application.__init__(self, handlers,**settings)

  class MainHandler(tornado.web.RequestHandler):

  def get(self):

  self.render(

  "index.html",

  )

  # 自己定义一个批量处理的方法

  def handle_formdata_args(self, query_title):

  result = dict()

  for title in query_title:

  value = self.get_argument(title) # 本质上还是用了get_argument方法获取值

  result[title] = value

  return result

  def post(self):

  ret =self.request.body # 二进制

  print("request.body:",ret,type(ret)) # request.body: b'title=22211&author=12333'

  # 提前吧需要查询的参数写进去 ―― 注意这里不能直接用json_decode!会报错!

  query_title=["title", "author"]

  req = self.handle_formdata_args(query_title)

  print("req:",req,type(req)) # req: {'title': '222', 'author': '123'}

  result =json.dumps(req,ensure_ascii=False) # 设置ensure_ascii=False 避免中文乱码

  self.write(result)

  if __name__=="__main__":

  tornado.options.parse_command_line()

  http_server = tornado.httpserver.HTTPServer(Application())

  http_server.listen(options.port)

  tornado.ioloop.IOLoop.instance().start()

  更方便的方法

  # -*- coding:utf-8 -*-

  import json

  import os.path

  import tornado.locale

  import tornado.httpserver

  import tornado.ioloop

  import tornado.options

  import tornado.web

  from tornado.options import define, options

  define("port", default=8006, help="run on the given port", type=int)

  class Application(tornado.web.Application):

  def __init__(self):

  handlers = [

  # 主页

  (r"/index", MainHandler),

  ]

  settings = dict(

  template_path=os.path.join(os.path.dirname(__file__),"templates"),

  static_path=os.path.join(os.path.dirname(__file__),"static"),

  debug=True,

  )

  # 执行父类__init__方法

  tornado.web.Application.__init__(self, handlers,**settings)

  class MainHandler(tornado.web.RequestHandler):

  def get(self):

  self.render(

  "index.html",

  )

  def handle_formdata_args2(self):

  result = dict()

  body =self.request.body # 二进制

  print("request.body:", body, type(body)) # request.body: b'title=123123&author=123'

  body_str=body.decode("utf-8")

  print("body_str:",body_str,type(body_str)) # body_str: title=123123&author=123

  # 根据规律切割body_str,找出来所有的"key" ―― 特别注意:"key"不能有中文!!!否则这个方法不能用!用上面介绍的方法!!!

  query_lst=body_str.split("&",1) # 切割一次防止用户输入的也有&号!

  print(query_lst) # ['title=123123', 'author=123']

  title_lst= []

  for query_str in query_lst:

  title =query_str.split("=",1)[0] # 切割一次!防止用户输入的也有等号!

  title_lst.append(title)

  print(title_lst) # ['title', 'author']

  for title in title_lst:

  value = self.get_argument(title)

  result[title] = value

  return result

  def post(self):

  req = self.handle_formdata_args2()

  result =json.dumps(req,ensure_ascii=False)

  self.write(result)

  if __name__=="__main__":

  tornado.options.parse_command_line()

  http_server = tornado.httpserver.HTTPServer(Application())

  http_server.listen(options.port)

  tornado.ioloop.IOLoop.instance().start()

  前端调试效果

  

  我们可以在基类的prepare方法中提前判断一下前端的请求头中contenttype的类型,然后将请求的数据封装成类的属性:

  

  接下来继承这个基类的子类就可以使用body_args这个属性 ―― 从前端获取的json格式的数据,来进行接下来的逻辑处理了。