Python的Tornado框架的REST支持方案

使用了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
     
     经测,可用,折腾死我了。
  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值