第十七天 實戰(zhàn)練習(4)
今天計劃用Python繼續(xù)一個web開發(fā)的實戰(zhàn)項目練習释漆,學習項目及練習源碼地址:
GitHub源碼
補坑
多個裝飾器
在處理session middware時遇到個奇怪的坑桥帆,經(jīng)調(diào)試發(fā)現(xiàn)耻卡,aiohttp_session在處理時是在app handler上加了一個裝飾器,和本來處理handler response的裝飾器發(fā)生沖突。專門研究了多個裝飾器的執(zhí)行順序問題。
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
'''
從上面的輸出,很容易首先是按裝飾器的的裝飾順序內(nèi)到外一次裝入宝踪,執(zhí)行的時候按裝入的順序執(zhí)行,最后執(zhí)行被裝飾的函數(shù)碍扔。
所以瘩燥,在實戰(zhàn)中需要將session裝飾器,放到response handler后面不同。
aiohttp_session.setup(app, storage)
app.middlewares.append(response_factory) #一定要放在session的后面,保證先執(zhí)行這個
如果從使用的角度來看厉膀,裝飾器其實是自頂向下的(畢竟實際使用過程中一般不會在外層打印信息)
意思就是說app.middlewares這個列表中定義的中間件,最先執(zhí)行的是列表最后一個元素二拐,然后依次序向上服鹅,這個在實際工作中一定要注意。
在servie層中定義is_login()裝飾器
為了保持路由層的簡潔百新,將一些常用的裝飾放入service中企软,這個也是符合業(yè)務邏輯的。判斷一個請求是否已經(jīng)登錄本身就是一個業(yè)務控制邏輯饭望。
aiohttp_jinja2模塊暫停使用
采用另一中方式來渲染模板仗哨,需要暫時停用aiohttp_jinja2形庭。它內(nèi)部提供的裝飾器與現(xiàn)有裝飾器有一定沖突。
統(tǒng)一處理返回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處理之后繼續(xù)進行處理厌漂,這個和之前的session有關系
return r
if isinstance(r, bytes):
# 最終返回到結(jié)果是經(jīng)過一些列封裝后的web.Response對象萨醒,在session中會繼續(xù)處理這個對象
預處理請求的數(shù)據(jù)
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書寫結(jié)構進行對比,此處的目的是預處理請求的參數(shù)苇倡,那么應該放在handler前面
綜上富纸,可以很好的理解多個裝飾器以及app.middware該如何使用了
找一個合適的模板
打算用傳統(tǒng)的bootstrap和jquery還實現(xiàn)期望的目的。
避開前后分離旨椒,注重于后端代碼的學習
計劃
下一次完成博客內(nèi)容的添加
- 完善用戶登錄和未登錄狀態(tài)
- 需要實現(xiàn)用戶在線通過富文本編輯博客內(nèi)容胜嗓。
- 展現(xiàn)文章列表和詳情