Рендеринг запрашиваемого типа в Торнадо - PullRequest
0 голосов
/ 06 декабря 2011

В 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')

~ edit ~ Я стрелял по чему-то похожему на реализацию рельсов, замеченную здесь

Ответы [ 3 ]

2 голосов
/ 07 декабря 2011

Я бы предпочел 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

Используйте параметр запроса для сериализации в соответствующий формат.

1 голос
/ 19 декабря 2011

Сначала настройте обработчики, чтобы рассчитывать на URI спокойного стиля. Мы используем 2 блока регулярного выражения в поисках идентификатора и потенциального формата запроса (например, 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, но вставил ее сюда для простоты понимания / экономии места), которая разделяет идентификаторы и форматы запросов. Поскольку вы должны ожидать идентификаторы в определенном порядке, я помещаю их в список.

Функция 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...
1 голос
/ 08 декабря 2011

mimetype - правильный способ сделать это, однако я вижу, где конечный пользователь захочет получить более упрощенный способ доступа к данным в желаемом формате.

Чтобы обеспечить совместимость со стандартами, соответствующими библиотекам и т. Д., Вы должны в конечном итоге определить тип ответа на основе запрошенного mimetype и ответить соответствующим mimetype в заголовках.

Чтобы достичь этого, ничего не нарушая, можно добавить синтаксический анализатор, который проверяет URI, запрошенный для суффикса, который соответствует кортежу определенных суффиксов, на которые может ответить маршрут, если это так, а mimetype не уже указано, измените переданный mimetype, чтобы он стал правильным типом суффикса.

Убедитесь, что окончательное решение основано на предоставленном mimetype, а не на суффиксе.

Таким образом, другие могут взаимодействовать с вашим сервисом RESTful так, как они привыкли, и вы все равно можете поддерживать простоту использования для людей и т. Д.

~ редактировать ~

Вот пример регулярного выражения, которое проверяет, заканчивается ли оно в .js | .html | .xml | .json. Это при условии, что вы указали полный URI.

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

Вот пример, который легче интерпретировать, но менее надежный

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

Эти регулярные выражения взяты из rfc2396

...