在Tornado中呈现请求的类型

时间:2011-12-06 19:57:41

标签: python request render tornado

在Tornado中,您如何区分不同的请求类型?另外,拆分请求的正确方法是什么?最后,如果我去/item/1.xml,我希望xml,/item / 1.html是一个合适的html视图等。

类似的东西:

def getXML():
    return self.render('somexmlresult.xml')

def getHTML():
    return self.rendeR('htmlresult.html')

def get():
    if request == 'xml':
        return self.render('somexmlresult.xml')
    elif request == 'html':
        return self.render('htmlresult.html')

编辑〜我正在拍摄铁路实施的内容here

3 个答案:

答案 0 :(得分:2)

我更喜欢自我描述的URL,就像RESTful应用程序一样。不需要url部分来表示资源的格式。 http://www.enterprise.com/customer/abc/order/123 必须代表资源,无论它是否为xml / html / json。发送请求格式的方法是将其作为请求参数之一发送。

http://www.enterprise.com/customer/abc/order/123?mimetype=application/xml
http://www.enterprise.com/customer/abc/order/123?mimetype=application/json
http://www.enterprise.com/customer/abc/order/123?mimetype=text/html

使用request参数序列化为适当的格式。

答案 1 :(得分:1)

mimetype是正确的方法,但我可以看到最终用户希望以更简单的方式访问他们希望的格式的数据。

为了保持与符合标准的库等的兼容性,您应该最终根据请求的mimetype确定响应类型,并使用标题中的相应mimetype进行响应。

实现这一目标而不破坏任何东西的方法是添加一个解析器来检查请求的后缀,该后缀匹配路由可以响应的已定义后缀的元组,如果有,并且mimetype不是已指定更改传入的mimetype为后缀的正确类型。

确保最终决定是基于提供的mimetype而不是后缀。

通过这种方式,其他人可以按照以前的方式与您的RESTful服务进行交互,并且您仍然可以保持对人类的易用性等。

〜编辑〜

下面是一个示例regexp,它检查它是否以.js |结尾.html | .xml |以.json。这假设你给出了完整的URI。

(?:([^:/?#]+):)?(?://([^/?#]*))?([^?#]*\.(?:js|html|xml|json))(?:\?([^#]*))?(?:#(.*))?

这是一个更容易理解但不太健壮的例子

^https?://(?:[a-z\-]+\.)+[a-z]{2,6}(?:/[^/#?]+)+\.(?:js|html|xml|json)$

这些正则表达式取自rfc2396

答案 2 :(得分:1)

首先,设置处理程序以依赖一个宁静的样式URI。我们使用2块正则表达式来寻找ID和潜在的请求格式(即html,xml,json等)

class TaskServer(tornado.web.Application):
    def __init__(self, newHandlers = [], debug = None):
        request_format = "(\.[a-zA-Z]+$)?"
        baseHandlers = [
            (r"/jobs" + request_format, JobsHandler),
            (r"/jobs/", JobsHandler),
            (r"/jobs/new" + request_format, NewJobsHandler),
            (r"/jobs/([0-9]+)/edit" + request_format, EditJobsHandler)
        ]
        for handler in newHandlers:
            baseHandlers.append(handler)


    tornado.web.Application.__init__(self, baseHandlers, debug = debug)

现在,在处理程序中定义一个可重用的函数parseRestArgs(我把它放在一个BaseHandler中,但为了便于理解/节省空间而粘贴在这里),它分割出ID和请求格式。因为你应该按照特定的顺序期待id,所以我把它们放在一个列表中。

get函数可以抽象得更多,但它显示了将逻辑拆分成不同请求格式的基本思路......

class JobsHandler(BaseHandler):
    def parseRestArgs(self, args):
        idList = []
        extension = None
        if len(args) and not args[0] is None:
            for arg in range(len(args)):
                match = re.match("[0-9]+", args[arg])
                if match:
                    slave_id = int(match.groups()[0])

            match = re.match("(\.[a-zA-Z]+$)", args[-1])
            if match:
                extension = match.groups()[0][1:]

        return idList, extension

    def get(self, *args):
        ### Read
        job_id, extension = self.parseRestArgs(args)

        if len(job_id):
            if extension == None or "html":
               #self.render(html) # Show with some ID voodoo
               pass
            elif extension == 'json':
                #self.render(json) # Show with some ID voodoo
                pass
            else:
                raise tornado.web.HTTPError(404) #We don't do that sort of thing here...
        else:
            if extension == None or "html":
                pass
                # self.render(html) # Index- No ID given, show an index
            elif extension == "json":
                pass
                # self.render(json) # Index- No ID given, show an index
            else:
                raise tornado.web.HTTPError(404) #We don't do that sort of thing here...