2018-12-17 初識Flask

一、flask介紹

??Flask和Django一樣,也是一個基于MVC設(shè)計模式的Web框架

??Flask流行的主要原因:

    1. 有非常齊全的官方文檔,上手非常方便
        
    2. 有非常好的拓展機(jī)制和第三方的拓展環(huán)境,工作中常見的軟件都有對應(yīng)的拓展,自己動手實現(xiàn)拓展也很容易
                
    3. 微型框架的形式給了開發(fā)者更大的選擇空間

二、安裝flask

    pip install flask

三、安裝管理庫

    pip install flask-script

四、導(dǎo)入管理庫中的Manager,用Manager管理項目

將flask對象交給Manager管理如下
manage = Manager(app)
manage.run()

??用manage啟動項目

    python hello.py runserver -h 0.0.0.0 -p 8080 -d

??參數(shù)說明:

    -h 指定主機(jī)地址
    -p 指定端口號
    -d 指定用debug方式啟動 
    
    路由接收參數(shù)
    @app.route('/stu/<id>/')
    def stu(id):
        # 接收的參數(shù)是字符串
        return f'stu id: {id}'
    
    @app.route('/grade/<int:id>/')
    def grade(id):
        # 指定接收的參數(shù)是int類型
        return f'grade id: {id}'

    可以指定許多接收參數(shù)類型但常用的就是int和string
@app.route('/path/<path:url>/')
def get_path(url):
    # 接收url中path后面的全部路徑
    return f'url: {url}'


@app.route('/get_uuid/')
def get_uuid():
    import uuid
    # 獲取一個uuid,uuid是一個唯一的字符串
    return str(uuid.uuid4())


@app.route('/uuid/<uuid:u>/')
def my_uuid(u):
    # 指定接收的參數(shù)為uuid類型的值
    return f'uuid: {u}'

??python框架主要

    Django
    Flask
    Tronado  
    Sanic    性能最優(yōu)但是一般不再線上使用
    Twisted  主要是針對底層協(xié)議

??將flask項目提煉成mvc的形式

??安裝藍(lán)圖(就是模塊化管理路由),相當(dāng)于Django中的urls.py

    pip install flask-blueprint

??使用:

    from flask import Blueprint
    # 模塊化管理路由 Blueprint
    # 第一步:生成藍(lán)圖對象
    blueprint = Blueprint('first', __name__)
    # 第二步:在管理文件中注冊一個藍(lán)圖,也就是將應(yīng)用綁定在應(yīng)用上
    app.register_blueprint(blueprint=blueprint, url_prefix='/app')
    # url_prefix: url訪問前綴127.0.0.1/app/
    前綴相當(dāng)于Django中的namespace

??路由跳轉(zhuǎn)

@blueprint.route('/redirect/')
def my_redirect():
    # 跳轉(zhuǎn)到無參方法
    # redirect: 跳轉(zhuǎn)
    # url_for:反向解析出地址
    # 'first.hello_world': 藍(lán)圖第一個 參數(shù).跳轉(zhuǎn)到的函數(shù)名
    return redirect(url_for('first.hello_world'))

@blueprint.route('/redirect_id/')
def stu_redirect():
    # 有參數(shù)的跳轉(zhuǎn)
    return redirect(url_for('first.stu', id=3))

五、請求與相應(yīng)

??1. 請求:

@blueprint.route('/req/', methods=['GET', 'POST', 'PUT', 'PATCH', 'DELETE'])
def req():
    # methods = ['GET', 'POST']指定能接收的請求類型
    if request.method == 'GET':
        # 獲取get請求中的參數(shù)
        # request.agrs.get(key)
        # 獲取get請求中多個相同key的參數(shù)的值,返回列表
        # request.args.getlist(key)
        return 'hello get'

    if request.method == 'POST':
        # 獲取post請求中傳遞的參數(shù)
        # request.form.get(key)
        # 獲取post請求中相同key的參數(shù),返回列表
        # request.form.getlist(key)

??2. 響應(yīng):

    從flask中導(dǎo)入響應(yīng)模塊
    創(chuàng)建響應(yīng)對象
    res = make_response(響應(yīng)內(nèi)容,狀態(tài)碼)
    設(shè)置cookie
    res.set_cookie(key, value, max_age, expires)
    key: 鍵
    value: 值
    max_age: 過期時間,秒為單位
    expires: 過期時間,datetime為單位
    刪除cookie
    方式一: res.delete_cookie(key)
    方式二: res.set_cookie(key, value, max_age=0) 過期時間為0相當(dāng)于刪除

六、裝飾器驗證登錄狀態(tài)

??裝飾器的三個特點:

    1. 外層函數(shù)內(nèi)嵌內(nèi)層函數(shù)
    2. 內(nèi)層函數(shù)調(diào)用外層函數(shù)的參數(shù)
    3. 外層函數(shù)返回內(nèi)層函數(shù)

??自定義一個登錄簡單的登錄驗證裝飾器

from flask import session, redirect, url_for

from functools import wraps

def login_status(func):
    # 使用functools裝飾該內(nèi)嵌函數(shù),用于維持被裝飾函數(shù)的部分屬性,如__name__/__doc__/__module__
    @wraps(func)
    def check_login(*args, **kwargs):
        # 獲取登錄后在session中設(shè)置的user_id,由于標(biāo)識用戶登錄狀態(tài)
        user_id = session.get('user_id')
        if user_id:
            # 有user_id說明登錄,則繼續(xù)執(zhí)行被裝飾函數(shù)
            return func(*args, **kwargs)
        else:
            # 如果沒有user_id說明沒有登錄,則跳轉(zhuǎn)道登錄界面
            return redirect(url_for('first.hello_world'))

    return check_login

??functools庫函數(shù)簡介
??1. update_wrapper
??更新一個包裹(wrapper)函數(shù),使其看起來更像被包裹(wrapped)的函數(shù)。

??可選的參數(shù)指定了被包裹函數(shù)的哪些屬性直接賦值給包裹函數(shù)的對應(yīng)屬性,同時包裹函數(shù)的哪些屬性要更新而不是直接接受被包裹函數(shù)的對應(yīng)屬性,參數(shù)assigned的默認(rèn)值對應(yīng)于模塊級常量WRAPPER_ASSIGNMENTS(默認(rèn)地將被包裹函數(shù)的 namemodule,和 doc 屬性賦值給包裹函數(shù)),參數(shù)updated的默認(rèn)值對應(yīng)于模塊級常量WRAPPER_UPDATES(默認(rèn)更新wrapper函數(shù)的 dict 屬性)。

??這個函數(shù)的主要用途是在一個裝飾器中,原函數(shù)會被裝飾(包裹),裝飾器函數(shù)會返回一個wrapper函數(shù),如果裝飾器返回的這個wrapper函數(shù)沒有被更新,那么它的一些元數(shù)據(jù)更多的是反映wrapper函數(shù)定義的特征,無法反映wrapped函數(shù)的特性。

??2. wraps
??這個函數(shù)可用作一個裝飾器,簡化調(diào)用update_wrapper的過程,調(diào)用這個函數(shù)等價于調(diào)用partial(update_wrapper, wrapped = wrapped, assigned = assigned,updated = updated)。

from functools import wraps

def my_decorator(f):
    @wraps(f)
    def wrapper(*args,**kwds):
        print "Calling decorated function"
        return f(*args,**kwds)
    return wrapper

@my_decorator
def example():
    """DocString"""
    print "Called example function"

example()
print example.__name__
print example.__doc__

??控制臺輸出,

    Calling decorated function
    Called example function
    example
    DocString

??可以看到,最終調(diào)用函數(shù)example時,是經(jīng)過 @my_decorator裝飾的,裝飾器的作用是接受一個被包裹的函數(shù)作為參數(shù),對其進(jìn)行加工,返回一個包裹函數(shù),代碼使用 @functools.wraps裝飾將要返回的包裹函數(shù)wrapper,使得它的 name, module,和 doc 屬性與被裝飾函數(shù)example完全相同,這樣雖然最終調(diào)用的是經(jīng)過裝飾的example函數(shù),但是某些屬性還是得到維護(hù)。

如果在 @my_decorator的定義中不使用 @function.wraps裝飾包裹函數(shù),那么最終example.name 將會變成'wrapper',而example.doc 也會丟失。

將 @wraps(f)注釋掉,然后運行程序,控制臺輸出,

    Calling decorated function
    Called example function
    wrapper
    None

??所以在上面我們自定義的登錄狀態(tài)驗證裝飾器就需要用到functools庫中的wraps來裝飾內(nèi)嵌函數(shù),維持被裝飾的函數(shù)的_name_、_module_、_doc_屬性,如果不用wraps裝飾當(dāng)我們在視圖函數(shù)中進(jìn)行反向解析被裝飾函數(shù)時,會報如下錯誤:

1.png

如:

@blueprint.route('/')
@login_status
def hello_world():

    return 'hello'

@blueprint.route('/login/', methods=['GET', 'POST'])
def login():

    if request.method == 'GET':

        return render_template('login.html')

    if request.method == 'POST':
        # 模擬登錄
        username = request.form.get('username')
        password = request.form.get('password')
        if username == 'root' and password == '123123':
            # 設(shè)置session值
            session['user_id'] = 1
        return redirect(url_for('first.hello_world'))  # 如果沒有用@wraps裝飾裝飾器的內(nèi)嵌函數(shù)則者句話在做反向解析時就會拋出上面提到的異常

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容