1. 程式人生 > 實用技巧 >第一章 Flask基礎

第一章 Flask基礎

1. 框架對比

DjangoFlask
Admin - Model 原生無
Model 原生無
Form 原生無
session 有-顛覆認知(儲存到服務端記憶體中,瀏覽器的cookies中)
教科書式框架 第三方元件非常豐富。一切從簡
優勢對比
元件、功能全,教科書 輕,快
劣勢對比
佔用資源,cpu,ram 先天不足,第三方元件穩定性較差
建立專案複雜度高

2. Flask

  1. 安裝:pip3 install Flask

    • 直接建立python檔案

    • ps:不要使用工具中的外掛建立Flask專案

  2. 三行啟動flask專案

  3. Flask:框架原始碼

    • Jinja2:模版語言

    • MarkupSafe:render基於此,防止xss攻擊

    • Werkzeug:類似django的uwsgi底層都是基於wsgi,承載flask服務,類似tomcat

3. 建立專案

1. 建立py檔案

  • 設定DEBUG:專案會自動重啟

from flask import Flask
# 命名
app = Flask('app.py')
# 或 app = Flask(__name__)
app.config['DEBUG'] = True
# 或 app.debug = True

@app.route('/')
def
home(): return 'AH, you are visiting Flask-site!' if __name__ == '__main__': # 監聽地址和埠 app.run('0.0.0.0', 5000) # werkzeug呼叫run_simple # wsgi處理請求頭(閘道器介面) # wsgi處理後的資料,environment。

2. response

  • content type:瀏覽器根據此引數,判斷響應型別

1. "xxx"

  • django中的 HttpResponse('hello'),Flask是 'hello'

@app.route('
/index') def index(): return 'hello world i am Flask'

2. render_template

  • 響應模版,預設存放路徑 templates,開啟模版並替換,依賴包 MarkupSafe中的 Markup 傳送給瀏覽器

@app.route('/index')
def index():
      return render_template('index.html')

3. redirect

  • 在Response Header中加入 Location: '/login'

@app.route('/login')
def login():
      return render_template('/index')
  • 以上是web框架的三劍客

4. send_file()

  • response instance:流媒體型別

  • 開啟檔案並自動識別檔案型別,在content-type中新增檔案型別,content-type:檔案型別

  • 瀏覽器特性:可識別的 content-type 自動渲染,不識別時,自動下載該檔案

content-type(6)

  1. text/html

  2. text/plain,保留當前檔案格式

  3. image/jepg或者 image/png

  4. audio/mpeg:<video> ,應該是<audio>,chrome完成

  5. video/mp4:<video> 標籤

  6. application/x-msdownload:xx.exe

  • 檔案型別:一般是檔案第一行就是檔案型別

from flask import send_file
@app.route('/get_file')
def get_file():
      # 返回檔案內容,自動識別檔案型別
      return send_file('app.py')

5. jsonify

  • flask 1.1.1 版本中,dict直接作為返回值返回,無須 jsonify

  • 返回標準json格式字串,api介面,先序列化字典,並設定content-type: Application/json

@app.route('/get_json')
def get_json():
      d = {'k':'v'}
    return jsonify(d)

4. request

  • request在flask中是公共變數(頂頭小寫),請求上下文儲存機制

  • 從reqeust中獲取的資料型別為:ImmutableMultiDict([('id', '1')])

1. request.method
2. request.form                # 獲取 FormData 中資料(ajax)
                                 # request.from.to_dict():返回對應的字典
                               # 型別:ImmutableMultiDict([])
3. request.args                # 獲取url中的引數
4. reqeust.values            # 獲取 url 和 FormData 中的資料,如果key相同 url中的會覆蓋 form中資料
                            # CombinedMultiDict([ImmutableMultiDict([('id', '1')]), ImmutableMultiDict([])])
5. request.host                # ip + port
6. request.path                # url路由地址
7. request.url                # 完整路徑
8. request.cookies            # 字典,獲取瀏覽器請求時帶上的cookies
9. request.files            # 獲取 Form 中檔案,返回 FileStroage中有 save() 方法和 filename屬性
10.request.json                # 請求中的 Content-type:application/json
                               # 請求體中的資料被序列化到request.json中,以字典的形式存放
11.request.data                # Content-type 中不包含 Form 或 FormData,保留請求體中的原始資料,b""型別
from flask import Flask
app = Flask(__name__)

@app.route('/login', methods=['GET','POST',])
def login():
      # 優先判斷請求方式
    # 如果是GET請求
    if request.method == 'GET':
          return render_template('login.html')
    # 如果是POST請求,獲取 使用者名稱,密碼 校驗
    else: # 405 請求方式不被允許
          # request.form.to_dict()
        my_file = request.files.get('my_file')
        filename = my_file.filename
        filepath = os.path.join('avatar', filename)
        my_file.save(filepath)
        if request.form.get('username') == 'xxx':
              return 'Login OK!'
    return '200 ok'

if __name__ == '__main__':
        app.run()f
  • ImmutableMultiDict型別資料用法和dict型別相同,都有 values(), item(),keys() 方法

5. Jinja2

1. 與templates不同(4)

  1. {{ my_input(arg1, arg2...) }}:引用或執行,函式必須有括號

  2. {% %}:邏輯,方法需要有()

  3. dict型別可以使用 info['username']

  4. 如果變數沒有定義會報錯

2. 傳遞變數(關鍵字傳參)

app.config['DEBUG'] = True
或 app.debug = True

@app.route('/')
def stu():
      return render_template('stu.html', stu=STUDENT,)
app.run('0.0.0.0:9527')

3. 傳遞函式

  • @app.template_global():專案中任何地方都可以使用被裝飾的函式

@app.template_global()
def ab(a,b):
      return a+b

@app.route('/a')
def homea():
      return render_template('a.html', ab=ab)

4. 巨集指令

  • 在jinja2模版中使用

{% macro my_input(na, ty) %}
    <input type="{{ ty }}" name="{{ na }}">
{% endmacro %}
{{ my_input('username', 'text') }}

5. Markup

  • 在view 函式中,生成標籤在使用

from markupsafe import Markup

@app.route('/a')
def homea():
      inp = Markup("<input type='submit' value='xxx'>")
    return render_template('a.html', btn=inp)

def my_input(na, ty):
      s = f"<input type='{ty}' value='{na}'>"
    return Markup(s)
{{ btn | safe }}
{{ my_input('username', 'text') }}

6. session

  1. 基於請求上下文

  2. 一般和 request 一起匯入

  3. 交由客戶端保管機制,加密後存到瀏覽器的cookies中。儲存一串字串

  4. 原生:不建議新增過多的 key:values,健值對越多,瀏覽器需要儲存的cookies越長,Flask會先對健值對進行壓縮和加密

  5. flask理念:一切從簡為伺服器減輕壓力

  6. flask-session:把加密後的session從瀏覽器,移動到服務端

from flask import session
# 金鑰不能為空
app.secret_key = "1!@#$8943:''.,xvzn;5lk12@!lg)*743%^&"
# 裝飾器

def warpper(func):
      def inner(*args, **kwargs):
          # 校驗登入狀態、校驗session中有沒有 user key
          if session.get('user'):
              return func()
        else:  # 校驗失敗,跳轉到登入頁面
              return redirect('/login')
        return inner

@app.route('/login', methods=['GET', 'POST'])
def login():
      if request.method == 'GET':
          return render_template('login.html')
    else:
          if request.form.get('username') == 'henry':
              return 'Login OK!'
        else:
                return 'failed'

@app.route('/')
@warpper
def homea():
    return render_template('a.html')