Python学习笔记-第17天:实战练习(4)

第十七天 实战练习(4)

今天计划用Python继续一个web开发的实战项目练习,学习项目及练习源码地址:
GitHub源码

补坑

多个装饰器

在处理session middware时遇到个奇怪的坑,经调试发现,aiohttp_session在处理时是在app handler上加了一个装饰器,和本来处理handler response的装饰器发生冲突。专门研究了多个装饰器的执行顺序问题。

def decorator_a(func):
    print('Get in decorator_a')
    def inner_a(*args,**kwargs):
        print('Get in inner_a')
        res = func(*args,**kwargs)
        return res
    return inner_a

def decorator_b(func):
    print('Get in decorator_b')
    def inner_b(*args,**kwargs):
        print('Get in inner_b')
        res = func(*args,**kwargs)
        return res
    return inner_b


@decorator_b
@decorator_a
def f(x):
    print('Get in f')
    return x * 2
f(1)
'''
Get in decorator_a
Get in decorator_b
Get in inner_b
Get in inner_a
Get in f
'''

从上面的输出,很容易首先是按装饰器的的装饰顺序内到外一次装入,执行的时候按装入的顺序执行,最后执行被装饰的函数。

所以,在实战中需要将session装饰器,放到response handler后面。

aiohttp_session.setup(app, storage)
app.middlewares.append(response_factory) #一定要放在session的后面,保证先执行这个

如果从使用的角度来看,装饰器其实是自顶向下的(毕竟实际使用过程中一般不会在外层打印信息)

意思就是说app.middlewares这个列表中定义的中间件,最先执行的是列表最后一个元素,然后依次序向上,这个在实际工作中一定要注意。

在servie层中定义is_login()装饰器

为了保持路由层的简洁,将一些常用的装饰放入service中,这个也是符合业务逻辑的。判断一个请求是否已经登录本身就是一个业务控制逻辑。

aiohttp_jinja2模块暂停使用

采用另一中方式来渲染模板,需要暂时停用aiohttp_jinja2。它内部提供的装饰器与现有装饰器有一定冲突。

统一处理返回response

async def response_factory(app, handler):
    async def response(request):
        logging.info('Response handler...')
        r = await handler(request)
        if isinstance(r, web.StreamResponse):  # 这里期望是在handler处理之后继续进行处理,这个和之前的session有关系
            return r
        if isinstance(r, bytes):
# 最终返回到结果是经过一些列封装后的web.Response对象,在session中会继续处理这个对象

预处理请求的数据

async def data_factory(app, handler):
    async def parse_data(request):
        if request.method == 'POST':
            if request.content_type.startswith('application/json'):
                request.__data__ = await request.json()
                logging.info('request json: %s' % str(request.__data__))
            elif request.content_type.startswith('application/x-www-form-urlencoded'):
                request.__data__ = await request.post()
                logging.info('request form: %s' % str(request.__data__))
        return (await handler(request))
# 注意和上面的response书写结构进行对比,此处的目的是预处理请求的参数,那么应该放在handler前面

综上,可以很好的理解多个装饰器以及app.middware该如何使用了

找一个合适的模板

打算用传统的bootstrap和jquery还实现期望的目的。

避开前后分离,注重于后端代码的学习

计划

下一次完成博客内容的添加

  1. 完善用户登录和未登录状态
  2. 需要实现用户在线通过富文本编辑博客内容。
  3. 展现文章列表和详情

你可能感兴趣的:(Python学习笔记-第17天:实战练习(4))