Flask 視圖,中間件

視圖

FBV

def index(nid):
    
  
""" 請求相關信息 request.method     # 請求方式 request.args       # get 方式的參數獲取 request.form      # post 方式的參數獲取 request.values     request.cookies       request.headers request.path      # 請求資源路徑 request.full_path   # 請求所有資源漫畫 request.script_root request.url       # 所有請求路徑 (帶協議帶域名) request.files      # 請求文件 obj = request.files['the_file_name'] obj.save('/var/www/uploads/' + secure_filename(f.filename))
"""
dic = {"k1":"v1"}
  
""" 返回響應體的4種形式 字符串 jsonify 模板 跳轉 url """

  # return "index"
  # return jsonify(dic)   # return render_template("xxx.html",dic=dic) # 可帶數據傳遞   # return redirect(url_for("index")) #
跳轉經過 url_for 反向解析
  
   """ 定製響應頭的時候構造響應體用到 make_response """

  # 若是想設置響應頭和回顯cookie,就須要用到make_response
  # response = make_response(render_template('index.html'))
  # response = make_response("字符串")
  # response是flask.wrappers.Response類型
  # response.delete_cookie('key')
  # response.set_cookie('key', 'value')
  # response.headers['X-Something'] = 'A value'
  # return response

from flask import make_response,headers,set_cookie obj = make_response(jsonify(dic)) obj.headers["xxxxx"] = "123" obj.set_cookie("key","value") return obj

裝飾器實現中間件功能

預備處理視圖函數初始狀態html

@app.route('/index')
def index():
    if not session.get('user'):
        return redirect(url_for('login'))
    return render_template('index.html',stu_dic=STUDENT_DICT)

視圖級別加裝,比較適用於對少許視圖進行處理json

import functools
def auth(func):
    @functools.wraps(func)
    def inner(*args,**kwargs):
        if not session.get('user'):
            return redirect(url_for('login'))
        ret = func(*args,**kwargs)
        return ret
    return inner

@app.route('/index')
@auth
def index():
    return render_template('index.html',stu_dic=STUDENT_DICT)

全局級別加裝flask

@app.before_request
def xxxxxx():
    if request.path == '/login':
        return None

    if session.get('user'):
        return None

    return redirect('/login')

除了 before_request 之外還有其餘特殊裝飾器:緩存

1. before_request    誰先定義誰先執行
    執行多個 before 的時候若是再中間有返回值,對於after 的執行直接執行最後一次定義的那個
    
2. after_request    誰後定義誰執行 

3. before_first_request

4. template_global

5. template_filter

6. errorhandler
from flask import Flask
app = Flask(__name__)


@app.before_request
def x1():
    print('before:x1')
    return ''

@app.before_request
def xx1():
    print('before:xx1')


@app.after_request
def x2(response):
    print('after:x2')
    return response

@app.after_request
def xx2(response):
    print('after:xx2')
    return response



@app.route('/index')
def index():
    print('index')
    return "Index"


@app.route('/order')
def order():
    print('order')
    return "order"


if __name__ == '__main__':

    app.run()
befor/after_request 示例
from flask import Flask
app = Flask(__name__)

@app.before_first_request
def x1():
    print('123123')


@app.route('/index')
def index():
    print('index')
    return "Index"


@app.route('/order')
def order():
    print('order')
    return "order"


if __name__ == '__main__':

    app.run()
before_first_request 示例
@app.errorhandler(404)
def not_found(arg):
    print(arg)
    return "沒找到"
errorhandler 示例

CBV

def auth(func):
    def inner(*args, **kwargs):
        result = func(*args, **kwargs)
        return result
    return inner

# 繼承自views.MethodView        採用CBV寫法時,爲了簡單,都是採用繼承MethodView的方式寫的
class IndexView(views.MethodView):
    # methods = ['POST']  #只容許POST請求訪問
    decorators = [auth,]  #若是想給全部的get,post請求加裝飾器,就能夠這樣來寫,也能夠單個指定

    def get(self):   #若是是get請求須要執行的代碼
        v = url_for('index')
        print(v)
        return "GET"

    def post(self):  #若是是post請求執行的代碼
        return "POST"

app.add_url_rule('/index', view_func=IndexView.as_view(name='index'))  #name指定的是別名,會當作endpoint使用

 

def auth(func):
    def inner(*args, **kwargs):
        print('before')
        result = func(*args, **kwargs)
        print('after')
        return result
    return inner

# 也能夠再往上繼承自View
class IndexView(views.View):
    methods = ['GET']
    decorators = [auth, ]
    # 若是繼承自View,就須要dispatch_request
    def dispatch_request(self):
        print('Index')
        return 'Index!'

app.add_url_rule('/index', view_func=IndexView.as_view(name='index'))  # name=endpoint

文件上傳

客戶端

  • 必需要在表單中上傳
  • 提交方式必須是 post
  • enctype 屬性必須是 multipart/form-data
<form action="/login" method="post" enctype="multipart/form-data">
    上傳文件: <input type="file">
</form>

服務端

文件會上傳到緩存區, 經過 request.files 獲取上傳文件cookie

拿到返回值能夠調用 save , filename 方法session

f = request.file['name']

# f.save('路徑')
# f.filename # 獲得文件原始名稱

f.save('static/' + f.filename) # 若是不存在 static 會報錯

此方法在上傳重名文件的時候會覆蓋, 所以須要本身設定毫不會重名的方式,好比用時間戳app

中間件

首先要知道咱們利用請求擴展裏提供的裝飾器也可以作一些中間件的事,咱們這裏說的是根據flask的源碼流程進行自定義方法來實現中間件的操做socket

具體流程:

app.run會執行werkzeug(第三方WSGI模塊)中的run_simple方法,繼而執行inner方法,繼續執行make_server方法,ide

make_sever方法就會返回一個BaseWSGIServer對象,主要是起socket,函數

當有請求過來時就會觸發flask的call方法,繼而執行wsgi_app方法

利用app.run中的wsgi_app方法能夠自定義類,定義的_ _call_ _方法裏就能夠作一些中間件的事

from flask import Flask

app = Flask(__name__)

@app.route('/')
def index():
    return 'Hello World!'

class Md(object):
    def __init__(self,old_wsgi_app):
        self.old_wsgi_app = old_wsgi_app

    def __call__(self,  environ, start_response):
        print('開始以前')
        ret = self.old_wsgi_app(environ, start_response)
        print('結束以後')
        return ret

if __name__ == '__main__':
    app.wsgi_app = Md(app.wsgi_app)
    app.run()
相關文章
相關標籤/搜索