定义RequestHandler

    URL处理函数不一定是一个 coroutine ,因此我们用 RequestHandler() 来封装一个URL处理函数。

    RequestHandler 是一个类,由于定义了 call() 方法,因此可以将其实例视为函数。

    RequestHandler 目的就是从URL函数中分析其需要接收的参数,从 request 中获取必要的参数,调用URL函数,然后把结果转换为 web.Response 对象,这样,就完全符合 aiohttp 框架的要求:

    class RequestHandler(object):



    def init(self, app, fn):

    self.app = app

    self.func = fn





    @asyncio.coroutine

    def __call
    (self, request):

    kw = … 获取参数

    r = yield from self._func(**kw)

    return r

    再编写一个 add_route 函数,用来注册一个URL处理函数:

    def addroute(app, fn):

    method = getattr(fn, 'method', None)

    path = getattr(fn, 'route', None)

    if path is None or method is None:

    raise ValueError('@get or @post not defined in %s.' % str(fn))

    if not asyncio.iscoroutinefunction(fn) and not inspect.isgeneratorfunction(fn):

    fn = asyncio.coroutine(fn)

    logging.info('add route %s %s => %s(%s)' % (method, path, fn._name
    , ', '.join(inspect.signature(fn).parameters.keys())))

    app.router.add_route(method, path, RequestHandler(app, fn))

    最后一步,把很多次 add_route() 注册的调用:

    add_route(app, handles.index)

    add_route(app, handles.blog)

    add_route(app, handles.create_comment)



    变成自动扫描:

    # 自动把handler模块的所有符合条件的函数注册了:

    add_routes(app, 'handlers')

    add_routes() 定义如下:

    def addroutes(app, modulename):

    n = modulename.rfind('.')

    if n == (-1):

    mod = import(module_name, globals(), locals())

    else:

    name = module_name[n+1:]

    mod = getattr(__import
    (module_name[:n], globals(), locals(), [name]), name)

    for attr in dir(mod):

    if attr.startswith('
    '):

    continue

    fn = getattr(mod, attr)

    if callable(fn):

    method = getattr(fn, 'method', None)

    path = getattr(fn, 'route', None)

    if method and path:

    add_route(app, fn)

    最后,在 app.py 中加入 middleware jinja2 模板和自注册的支持:

    app = web.Application(loop=loop, middlewares=[

    logger_factory, response_factory

    ])

    init_jinja2(app, filters=dict(datetime=datetime_filter))

    add_routes(app, 'handlers')

    add_static(app)