Продвинутая маршрутизация Webapp2 - PullRequest
1 голос
/ 11 января 2012

В старом школьном веб-приложении маршрутизация на основе app.yaml позволяла вам проверять регулярные выражения и, в случае совпадения, обрабатывать запрос обработчиком, имя которого основано на найденном шаблоне. Например, \ 1_handler.py отправил бы в user_handler.py, если сопоставленный образец был 'user'.

Есть ли способ сделать то же самое с webapp2.Route? Могут ли ленивый обработчик или параметры method_handler быть основаны на сопоставленных шаблонах в шаблоне?

1 Ответ

4 голосов
/ 12 января 2012

webapp2 не позволяет так маршрутизировать. Я думаю, что самое разумное решение - написать собственный диспетчер для webapp2.Router.

Можно настроить пользовательский диспетчер следующим образом:

app = WSGIApplication(...)
app.router.set_dispatcher(custom_dispatcher)

Вот не проверенный эскиз для диспетчера, код основан на webapp2.Router.default_dispatcher:

from webapp2 import import_string

def custom_dispatcher(router, request, response):
    route, args, kwargs = rv = router.match(request)
    request.route, request.route_args, request.route_kwargs = rv

    handler = route.handler
    if isinstance(handler, basestring):

        handler, args, kwargs = _parse_handler_template(handler, args, kwargs)

        if handler not in self.handlers:
            router.handlers[handler] = handler = import_string(handler)
        else:
            handler = router.handlers[handler]

    return router.adapt(handler)(request, response)

def _parse_handler_template(handler, args, kwargs):
    """replace {key} in `handler` with values from `args` or `kwargs`.
    Replaced values are removed from args/kwargs."""
    args = list(args)
    kwargs = dict(kwargs)
    def sub(match):
        if kwargs:
            return kwargs.pop(match.group().strip('{}'))
        else:
            return args.pop(int(match.group().strip('{}'))
    return re.sub('{.*?}', sub, handler), args, kwargs

Этот код должен позволять регистрировать такие правила:

 app = WSGIApplication([
     (r'module/<module>/<action>/<argument>', 'modules.{module}.action_{action}'),
 ])

Этот пример не позволяет использовать переменные из шаблона в имени метода, например: module.Class:action_{method}. В классе Route эта конечная точка разделяется точкой с запятой и значения хранятся в route.method_name и route.handler.

...