1. 程式人生 > >Python中Web框架編寫學習心得

Python中Web框架編寫學習心得

記錄日誌 實例 心得 ret NPU oba esp ascii edi

學習廖雪峰老師的Python實戰教程,在Web框架這部分看了大致一個多禮拜,前面的知識學的不夠紮實,由於比較復雜,因此在這裏總結下,也算是鞏固了。

先看下框架的調用代碼:

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)
  1. 使用web.Application類創建aiohttp server——app,其中loop為Eventloop用來處理HTTP請求,middlewares為中間件,在這裏用來記錄日誌並處理handler返回的數據為web.response對象,這裏看下response_factory
    的代碼
async def response_factory(app, handler):
    async def response(request):
        logging.info(‘Response handler...‘)
        #獲取handler的返回值,根據返回值的不同類型進行處理
        r = await handler(request)
        print(type(r))
        if isinstance(r, web.StreamResponse):
            return r
        if isinstance(r, bytes):
            resp = web.Response(body=r)
            resp.content_type = ‘application/octet-stream‘
            return resp
        if isinstance(r, str):
            if r.startswith(‘redirect:‘):
                return web.HTTPFound(r[9:])
            resp = web.Response(body=r.encode(‘utf-8‘))
            resp.content_type = ‘text/html;charset=utf-8‘
            return resp
        if isinstance(r, dict):
            template = r.get(‘__template__‘)
            if template is None:
                resp = web.Response(body=json.dumps(r, ensure_ascii=False, default=lambda o: o.__dict__).encode(‘utf-8‘))
                resp.content_type = ‘application/json;charset=utf-8‘
                return resp
            else:
                resp = web.Response(body=app[‘__templating__‘].get_template(template).render(**r).encode(‘utf-8‘))
                resp.content_type = ‘text/html;charset=utf-8‘
                return resp
        if isinstance(r, int) and r >= 100 and r < 600:
            return web.Response(r)
        if isinstance(r, tuple) and len(r) == 2:
            t, m = r
            if isinstance(t, int) and t >= 100 and t < 600:
                return web.Response(t, str(m))
        # default:
        resp = web.Response(body=str(r).encode(‘utf-8‘))
        resp.content_type = ‘text/plain;charset=utf-8‘
        return resp
    return response
  1. 使用jinjia2模板來構建前端頁面,這裏我們暫時沒有用到
  2. 註冊處理url的handler,aiohttp中的add_route函數進行註冊,我們這裏使用add_routes對‘handlers‘模塊的handler進行批量註冊
def add_route(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))
def add_routes(app, module_name):
    #找到‘.‘則返回其所在位置,否則返回-1
    n = module_name.rfind(‘.‘)
    if n == (-1):
        #mod為包含module_name模塊中全部屬性和方法的list
        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):
        #檢查handler是否被@get或@post裝飾
        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)

這裏出現了一個RequestHandler類,它具有call魔術方法,所以可以像調用函數一樣調用其實例,這裏RequestHandler類主要是對handler進行封裝,獲取request中傳入的參數並傳入handler中。

  1. add_static是用戶處理如圖片、js、css等靜態資源的,僅供開發環境中方便使用,生產環境一般使用nginx或CDN之類的,這塊我也還沒有搞清楚,沒辦法梳理

最後把我的handler模塊的代碼貼出來,供參考:

from coroweb import get, post
from aiohttp import web

@get(‘/blog‘)
async def handler_url_blog(request):
    body=‘<h1>Awesome: /blog</h1>‘
    return body

@get(‘/greeting‘)
async def handler_url_greeting(*,name,request):
    body=‘<h1>Awesome: /greeting %s</h1>‘%name
    return body

@get(‘/input‘)
async def handler_url_input(request):
    body=‘<form action="/result" method="post">E-mail: <input type="email" name="user_email" /><input type="submit" /></form>‘
    return body

@post(‘/result‘)
async def handler_url_result(*,user_email,request):
    body=‘<h1>您輸入的郵箱是%s</h1>‘%user_email
    return body

@get(‘/index‘)
async def handler_url_index(request):
    body=‘<h1>Awesome: /index</h1>‘
    return body

@get(‘/create_comment‘)
async def handler_url_create_comment(request):
    body=‘<h1>Awesome: /create_comment</h1>‘
    return body


作者:糊君
鏈接:https://www.jianshu.com/p/0fded26001e3
來源:簡書
簡書著作權歸作者所有,任何形式的轉載都請聯系作者獲得授權並註明出處。

Python中Web框架編寫學習心得