您的位置:首页 > 编程语言 > Python开发

Python的Tornado框架的REST支持方案

2014-11-13 18:00 127 查看
使用了Python的Tornado框架,想发布为REST规范的webservice.综合了网上的方法,基本上有三种:

1. 直接用tornado实现:

tornado.web.RequestHandler.write() 可以输出json.

但是对于header的操作需要自己封装。

本着拿来主义的精神,还是想找现成的插件。

2. 有一个叫pyrestful的插件,可以试用一下。

步骤如下:

a. pip install pyrestful

b. 可以参考官方文档,我的代码片段如下:

*入口代码:

#!/usr/bin/python
#-*- coding: utf-8 -*-

__author__ = 'stone'

import tornado.ioloop

import pyrestful.rest

import os

os.environ['NLS_LANG'] = 'SIMPLIFIED CHINESE_CHINA.UTF8'

import logging

from common.Log import LogInit

from common.Cfg import config

from business.Customer import CustomerResource

LogInit("loggingREST.conf")

cfg = config(filename="config4REST.conf")

#a list to route different REST Service.

restservices = []

restservices.append(CustomerResource)

if __name__ == "__main__":

loggerRoot = logging.getLogger('root')

loggerRoot.debug("start run REST module.")

try:

app = pyrestful.rest.RestService(restservices)

port = cfg.get('port','port')

app.listen(port)

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

except Exception,ex:

pass



*服务代码:

__author__ = 'stone'
#-*- coding: utf-8 -*-
import os
os.environ['NLS_LANG'] = 'SIMPLIFIED CHINESE_CHINA.UTF8'
import pyrestful.rest
from pyrestful import mediatypes
from pyrestful.rest import get, post, put, delete
import logging
import torndb

class Customer(object):
def __init__(self,id_customer=0, name_customer=None, address_customer=None):
self.id_customer = id_customer
self.name_customer = name_customer
self.address_customer = address_customer

# Setters
def setId_Customer(self,id_customer):
self.id_customer = id_customer
def setName_Customer(self,name_customer):
self.name_customer = name_customer
def setAddress_Customer(self,address_customer):
self.address_customer = address_customer

# Getters
def getId_Customer(self):
return self.id_customer
def getName_Customer(self):
return self.name_customer
def getAddress_Customer(self):
return self.address_customer

class CustomerDataBase(object):
customerDB = dict()
id_seq = 1
def insert(self, name_customer, address_customer):
sequence = self.id_seq
customer = Customer(sequence, name_customer, address_customer)
self.customerDB[sequence] = customer
self.id_seq += 1
return sequence

def update(self,id_customer, name_customer, address_customer):
if self.exists(id_customer):
customer = self.customerDB[id_customer]
customer.setName_Customer(name_customer)
customer.setAddress_Customer(address_customer)
self.customerDB[id_customer] = customer
return True
else:
return False

def delete(self,id_customer):
if self.exists(id_customer):
del self.customerDB[id_customer]
return True
else:
return False

def find(self,id_customer):
if self.exists(id_customer):
return self.customerDB[id_customer]
else:
return None

def exists(self,id_customer):
if id_customer in self.customerDB:
return True
else:
return False

class CustomerResource(pyrestful.rest.RestHandler):
"""
a class for Customer Resource.
"""
def initialize(self):
"""
special initial for tornado.web.RequestHandler.
"""
loggerRoot = logging.getLogger('root')
loggerRoot.debug("start CustomerResource module.")
self.database = CustomerDataBase()

#REST-GET
@get(_path="/customer/{id_customer}",_types=[int],_produces=mediatypes.APPLICATION_JSON)
def getTest(self,id_customer):
try:
if not self.database.exists(id_customer):
self.gen_http_error(404,"Error 404 : do not exists the customer : %d"%id_customer)
return

customer = self.database.find(id_customer)

response = dict()
response['id_customer'] = customer.getId_Customer()
response['name_customer'] = customer.getName_Customer()
response['address_customer'] = customer.getAddress_Customer()
return response
except Exception,ex:
pass

#REST-POST
@post(_path="/customer", _types=[str,str], _produces=mediatypes.APPLICATION_JSON)
def createCustomer(self, name_customer, address_customer):
try:
id_customer = self.database.insert(name_customer, address_customer)
return {"created_customer_id": id_customer}
except Exception,ex:
pass

#REST-PUT
@put(_path="/customer/{id_customer}", _types=[int,str,str], _produces=mediatypes.APPLICATION_JSON)
def updateCustomer(self, id_customer, name_customer, address_customer):
try:
if not self.database.exists(id_customer):
self.gen_http_error(404,"Error 404 : do not exists the customer : %d"%id_customer)
return
updated = self.database.update(id_customer,name_customer,address_customer)
return {"updated_customer_id": id_customer, "success":updated}
except Exception,ex:
pass

#REST-DELETE
@delete(_path="/customer/{id_customer}", _types=[int], _produces=mediatypes.APPLICATION_JSON)
def deleteCustomer(self,id_customer):
try:
if not self.database.exists(id_customer):
self.gen_http_error(404,"Error 404 : do not exists the customer : %d"%id_customer)
return
deleted = self.database.delete(id_customer)
return {"delete_customer_id": id_customer, "success":deleted}
except Exception,ex:
pass





经过测试可用。

3. 但是,之前用的web.py框架时,有一个叫做mimerender的插件,封装比这个优雅,想用起来,这一折腾就花了3天,最终调通,使用方法如下:

a. pip install mimerender.

b. hacker mimerender的代码,添加tornado的支持,片段如下:

# tornado implementation
try:
import tornado.web
class TornadoMimeRender(MimeRenderBase):
"""
a class for tornado mimerender.
2014.11.13. stone spend a week to use it.
we need set the handler from front app.
"""

#a class hander for tornado
localHandler = tornado.web.RequestHandler
def setHandler(self,reqHandler):
"""
set the handler for tornado.
"""
self.localHandler = reqHandler

def _get_request_parameter(self, key, default=None):
#tornado.web.RequestHandler.get_argument()
return self.localHandler.get_argument(key,default)

def _get_accept_header(self, default=None):
return self.localHandler.request.headers['ACCEPT']

def _set_context_var(self, key, value):
#tornado.web.RequestHandler.__setattr__(key,value)
self.localHandler.__setattr__(key,value)

def _clear_context_var(self, key):
#tornado.web.RequestHandler.__delattr__(key)
self.localHandler.__delattr__(key)

def _make_response(self, content, content_type, status):
#tornado.web.RequestHandler.set_status(status)
# we only need first 3 int.
self.localHandler.set_status(int(status[0:3]))
#tornado.web.RequestHandler.set_header('Content-Type',content_type)
self.localHandler.set_header('Content-Type',content_type)
self.localHandler.write(content)

except ImportError:
pass



c. 使用的代码片段如下:

#!/usr/bin/python
#-*- coding: utf-8 -*-
__author__ = 'stone'
import tornado.ioloop
import tornado.web
import mimerender
import json
import os
os.environ['NLS_LANG'] = 'SIMPLIFIED CHINESE_CHINA.UTF8'
import logging
from common.Log import LogInit
from common.Cfg import config

LogInit("loggingREST.conf")

cfg = config(filename="config4REST.conf")

mimerender = mimerender.TornadoMimeRender()

render_xml = lambda message: '<message>this is xml:%s</message>'%message
render_json = lambda **args: json.dumps(args)
render_html = lambda message: '<html><body>this is html:%s</body></html>'%message
render_txt = lambda message: message

class Mimeservice(tornado.web.RequestHandler):
"""
a mime render test service.
"""

#use mimerender
#step 1: set the handler.
def initialize(self):
"""
special init for tornado.web.RequestHandler class.
set the handler for mime render.
"""
mimerender.setHandler(self)

#use mimerender
#step 2: define mimerender format.
@mimerender(
default = 'json',
html = render_html,
xml = render_xml,
json = render_json,
txt = render_txt
)
#use mimerender
#step 3: same with the all mimerender.
def get(self):
return {'message':'Hello'}

application = tornado.web.Application([
(r"/mimeservice",Mimeservice),
(r"/mime",Mimeservice)
])

if __name__ == "__main__":
loggerRoot = logging.getLogger('root')
loggerRoot.debug("start run REST module in mimerender.")
try:
port = cfg.get('port','port')
application.listen(port)
tornado.ioloop.IOLoop.instance().start()
except Exception,ex:
pass


经测,可用,折腾死我了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: