python之初識Flask

1、初識Flask

Python三大主流Web框架對比

一、三大框架的特色

  • Django 主要特色是大而全,集成了不少組件,例如: Models Admin Form 等等, 無論你用獲得用不到,反正它全都有,屬於全能型框架
  • Tornado 主要特色是原生異步非阻塞,在IO密集型應用和多任務處理上佔據絕對性的優點,屬於專一型框架
  • Flask 主要特色小而輕,原生組件幾乎爲0, 三方提供的組件請參考Django 很是全面,屬於短小精悍型框架

二、三大框架的優缺點 html

  • Django 一般用於大型Web應用因爲內置組件足夠強大因此使用Django開發能夠一鼓作氣
  • Tornado 一般用於API後端應用,遊戲服務後臺,其內部實現的異步非阻塞真是穩得一批
  • Flask 一般應用於小型應用和快速構建應用,其強大的三方庫,足以支撐一個大型的Web應用
  • Django 優勢是大而全,缺點也就暴露出來了,這麼多的資源一次性所有加載,確定會形成一部分的資源浪費
  • Tornado 優勢是異步,缺點是乾淨,連個Session都不支持
  • Flask 優勢是精悍簡單,缺點是組件大都來自第三方等

關於上面的總結前端

Django:python

  優勢:mysql

    大而全,admin,models,Form,中間件,sessionweb

    一個框架解決全部問題sql

  缺點:json

    一旦啓動,全部資源所有加載,用不到的,浪費了flask

    太大了,結構複雜後端

    全部的組件,所有由Django自身控制瀏覽器

Flask:

  優勢:

    輕、短小精悍

    快、最短三行代碼就能開啓服務

  缺點:

    組件大部分都來自第三方,如flask-admin, flask-session

    flask大版本更新,組件更新速度慢

 

Tornado:

  優勢:

    原生的websocket

    異步io

    非阻塞

  缺點:

    三方和原組件幾乎爲零

Flask的準備工做

首先咱們要安裝Flask,具體操做以下:

  pip install Flask   

也能夠經過pycharm在裏面直接搜索Flask點擊安裝就好。還有其餘的一些安裝在這裏就不在說了

 

三行代碼啓動Flask

from flask import Flask
app = Flask(__name__)
app.run()

 

  執行上面的代碼我麼在控制檯能夠看到一下一行代碼

* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)

 

從上面能夠看出默認訪問的端口是5000,

咱們訪問該頁面

上面給個人提示是沒有相應的路由,由於咱們根本沒有配置,不過這個時候服務已經起來了

這個就是三行代碼啓動Flask服務

 

咱們來寫一個真正的第一個flask程序

from flask import Flask  # 導入Flask類

# 實例化一個Flask對象,傳遞__name__參數進去
app = Flask(__name__)


# url與視圖映射
@app.route('/')  # app中的route裝飾器
def hello_world():  # 視圖函數
    return 'Hello World!'  # 返回的響應體


if __name__ == '__main__':
    # 這裏面的端口咱們是能夠本身設置的,我這裏就沒有設置了仍是默認的5000
    # debug=True表示啓動debug模式。當代碼有改動時,Flask會自動加載,無序重啓!默認是關閉的
    app.run(debug=True)  # 啓動Flask服務

 啓動上面代碼並訪問相應的頁面咱們在頁面上就會看到'Hello World'的字樣

路由系統

url傳參的方式

普通的傳參

@app.route('/user/<id>/')  # app中的route裝飾器
def hello_world(id):  # 視圖函數
    return '你是第{}個用戶'.format(id)  # 返回的響應體

指定參數類型

有如下幾種參數類型:

  • string:默認的數據類型
  • int:接收整型
  • float:浮點型
  • path:和string相似,這裏能夠接收斜槓
  • any:能夠指定多個路徑
  • uuid:只接受uuid字符串

(1) any

@app.route('/<any(blog,user):url_path>/<id>/')
def detail(url_path,id):
    if url_path == 'blog':
        return '博客詳情{}'.format(id)
    else:
        return '用戶詳情{}'.format(id)

 

 

注意:上面的路由 '/<any(blog,user):url_path>/<id>/'寫的時候必定要加上'/'反斜槓,要不會出錯

 (2)path

@app.route('/article/<path:test>/')
def test_article(test):
    return 'test_article:{}'.format(test)

 有上面的圖片能夠看出來只要是前面匹配成功了,後面全部的包含'/'都會當作path。

endpoint

endpoint:反向生成url

#!/usr/bin/env python
# -*-coding:utf-8-*-
from flask import Flask  # 導入Flask類
from flask import url_for

app = Flask(__name__)


# 這裏的endpoint咱們能夠不寫,不寫就默認爲index和函數名同樣
@app.route('/index/', endpoint='first')
def index():
    print(url_for('first'))  # 若是上面沒有穿endpoint得話就寫'index'
    return 'ok'


if __name__ == '__main__':
    # 這裏面的端口咱們是能夠本身設置的,我這裏就沒有設置了仍是默認的5000
    # debug=True表示啓動debug模式。當代碼有改動時,Flask會自動加載,無序重啓!默認是關閉的
    app.run(debug=True)  # 啓動Flask服務

 

訪問:http://127.0.0.1:5000/index/

pycharm控制檯獲得

/index/

 

這個不算是完整的url要想獲得完整的url咱們修改後爲

#!/usr/bin/env python
# -*-coding:utf-8-*-
from flask import Flask  # 導入Flask類
from flask import url_for

app = Flask(__name__)


# 這裏的endpoint咱們能夠不寫,不寫就默認爲index和函數名同樣
@app.route('/index/', endpoint='first')
def index():
    print(url_for('first',_external=True))  # 若是上面沒有穿endpoint得話就寫'index'
    return 'ok'


if __name__ == '__main__':
    # 這裏面的端口咱們是能夠本身設置的,我這裏就沒有設置了仍是默認的5000
    # debug=True表示啓動debug模式。當代碼有改動時,Flask會自動加載,無序重啓!默認是關閉的
    app.run(debug=True)  # 啓動Flask服務

 

pycharm控制檯輸出爲:

http://127.0.0.1:5000/index/

 

這樣仍是不夠當咱們後面有參數的時候怎麼辦

使用下面的方式:

#!/usr/bin/env python
# -*-coding:utf-8-*-
from flask import Flask  # 導入Flask類
from flask import url_for,request

app = Flask(__name__)


# 這裏的endpoint咱們能夠不寫,不寫就默認爲index和函數名同樣
@app.route('/index/', endpoint='first')
def index():
    stu_id = int(request.args['id'])
    print(url_for('first', _external=True, id=stu_id))  # 若是上面沒有穿endpoint得話就寫'index'
    return 'ok'


if __name__ == '__main__':
    # 這裏面的端口咱們是能夠本身設置的,我這裏就沒有設置了仍是默認的5000
    # debug=True表示啓動debug模式。當代碼有改動時,Flask會自動加載,無序重啓!默認是關閉的
    app.run(debug=True)  # 啓動Flask服務

 

訪問:http://127.0.0.1:5000/index/?id=1

pycharm控制檯獲得的輸出爲:

http://127.0.0.1:5000/index/?id=1

 

defaults

defaults : 視圖函數的參數默認值{"nid":100}

注意:視圖函數必需要設置形參nid,不然報錯!

 

#!/usr/bin/env python
# -*-coding:utf-8-*-
from flask import Flask  # 導入Flask類
from flask import url_for,request

app = Flask(__name__)


# 這裏的endpoint咱們能夠不寫,不寫就默認爲index和函數名同樣
@app.route('/index/', endpoint='first', defaults={'nid':100})
def index(nid):
    stu_id = int(request.args['id'])
    print(url_for('first', _external=True, id=stu_id))  # 若是上面沒有穿endpoint得話就寫'index'
    print(nid)
    return 'ok'


if __name__ == '__main__':
    # 這裏面的端口咱們是能夠本身設置的,我這裏就沒有設置了仍是默認的5000
    # debug=True表示啓動debug模式。當代碼有改動時,Flask會自動加載,無序重啓!默認是關閉的
    app.run(debug=True)  # 啓動Flask服務

 

訪問:http://127.0.0.1:5000/index/?id=1

pycharm獲得的結果爲:

http://127.0.0.1:5000/index/?id=1
100

 

訪問一個結尾不帶斜線的url會被flask重定向到一個帶斜線的規範url去,因此咱們在寫的時候仍是要在路由後面加一個斜線

 

 

 響應

響應體 HttpResponse、Render、Redirect、jsonify

 HttpResponse

@app.route("/")  # app中的route裝飾器
def index():  # 視圖函數
    return "Hello World!"  # HttpResponse

在flask中的HttpResponse 其實就是直接返回字符串

 redirect

#!/usr/bin/env python
# -*-coding:utf-8-*-
from flask import Flask  # 導入Flask類
from flask import redirect

# 實例化一個Flask對象,傳遞__name__參數進去
app = Flask(__name__)


# url與視圖映射
@app.route('/redi/')
def redi():
    return redirect('/')  # redirect跳轉至"/"


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


if __name__ == '__main__':
    # 這裏面的端口咱們是能夠本身設置的,我這裏就沒有設置了仍是默認的5000
    # debug=True表示啓動debug模式。當代碼有改動時,Flask會自動加載,無序重啓!默認是關閉的
    app.run(debug=True)  # 啓動Flask服務

在上面咱們啓動後訪問:  http://127.0.0.1:5000/redi/

會看到Hello World

render

#!/usr/bin/env python
# -*-coding:utf-8-*-
from flask import Flask  # 導入Flask類
from flask import render_template  # 導入flask中的render_template

# 實例化一個Flask對象,傳遞__name__參數進去
app = Flask(__name__)

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


if __name__ == '__main__':
    # 這裏面的端口咱們是能夠本身設置的,我這裏就沒有設置了仍是默認的5000
    # debug=True表示啓動debug模式。當代碼有改動時,Flask會自動加載,無序重啓!默認是關閉的
    app.run(debug=True)  # 啓動Flask服務

在當前的py文件的同級目錄下建立一個templates目錄而後在該目錄下建立一個index.html文件

index.html內容以下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>Hello World!</h1>
</body>
</html>

 咱們能夠重啓後訪問後會出現一下結果

 

 

在上面咱們寫return render_template('index.html')

 會發現index.html這個飄黃咱們能夠在pycharm的右擊templates -> Mark Directory as-->Template Folder

會跳出來一個選項選擇yes就好,而後出來一個界面在右邊有一個Tempalte language在後面咱們選擇Jinja2而後點擊肯定就好

 若是咱們使用pycharm建立一個Flask項目就不會出現這個問題,可是現階段建議本身手動操做,有利於更好的熟悉flask

jsonify

後端代碼爲

#!/usr/bin/env python
# -*-coding:utf-8-*-
from flask import Flask  # 導入Flask類
from flask import jsonify  # 導入flask中的jsonify

# 實例化一個Flask對象,傳遞__name__參數進去
app = Flask(__name__)


@app.route('/index/')
def index():
    return jsonify({'k1':'v1'})


if __name__ == '__main__':
    # 這裏面的端口咱們是能夠本身設置的,我這裏就沒有設置了仍是默認的5000
    # debug=True表示啓動debug模式。當代碼有改動時,Flask會自動加載,無序重啓!默認是關閉的
    app.run(debug=True)  # 啓動Flask服務

訪問http://127.0.0.1:5000/index/

獲得下圖:

定製響應頭。

flask如何給本身定製一個響應頭信息

後端代碼爲

#!/usr/bin/env python
# -*-coding:utf-8-*-
from flask import Flask  # 導入Flask類
from flask import make_response  # make_response專門是用來設置響應頭的

# 實例化一個Flask對象,傳遞__name__參數進去
app = Flask(__name__)


@app.route('/index/')
def index():
    obj = make_response('qwer')
    obj.headers['aaaa'] = '123'
    obj.set_cookie('key', 'value')
    return obj


if __name__ == '__main__':
    # 這裏面的端口咱們是能夠本身設置的,我這裏就沒有設置了仍是默認的5000
    # debug=True表示啓動debug模式。當代碼有改動時,Flask會自動加載,無序重啓!默認是關閉的
    app.run(debug=True)  # 啓動Flask服務

 

訪問:http://127.0.0.1:5000/index/

咱們能夠看到瀏覽器中信息

頁面爲:

點擊右鍵選擇 檢查(使用的是Google Chrome)

 

 能夠看到咱們在上面設置的請求頭在這裏可以看到

再看看咱們的cookie

這個就是咱們定製的響應頭

 

request相關

每一個框架中都有處理請求的機制(request),可是每一個框架的處理方式和機制是不一樣的

爲了瞭解Flask的request中都有什麼東西,首先咱們要寫一個先後端的交互

基於HTML + Flask 寫一段先後端的交互

先寫一段兒HTML form表單中提交方式是post  action地址是 /test

login.html的代碼爲

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>歡迎登錄</h1>
<form action="/test/" method="post">
    <p>
        <input type="text" name="user" placeholder="請輸入用戶名">
    </p>
    <p>
        <input type="password" name="pwd" placeholder="請輸入密碼">
    </p>
    <input type="submit" value="提交">
</form>
</body>
</html>

咱們寫的flask的代碼爲

#!/usr/bin/env python
# -*-coding:utf-8-*-
from flask import Flask  # 導入Flask類
from flask import render_template  # 導入flask中的render_template
from flask import request

# 實例化一個Flask對象,傳遞__name__參數進去
app = Flask(__name__)


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


@app.route('/test/')
def home():
    print(request)
    return 'ok'


if __name__ == '__main__':
    # 這裏面的端口咱們是能夠本身設置的,我這裏就沒有設置了仍是默認的5000
    # debug=True表示啓動debug模式。當代碼有改動時,Flask會自動加載,無序重啓!默認是關閉的
    app.run(debug=True)  # 啓動Flask服務

咱們訪問http://127.0.0.1:5000/login/頁面後隨便輸入用戶名和密碼或者直接提交就會出現下面的圖示

這個提示是其請求的方式不被容許。

這個請求的方式不被容許是由於默認的路由只容許GET,咱們提交的是POST因此這裏不經過

request.methods

修改咱們的flask代碼

#!/usr/bin/env python
# -*-coding:utf-8-*-
from flask import Flask  # 導入Flask類
from flask import render_template  # 導入flask中的render_template
from flask import request

# 實例化一個Flask對象,傳遞__name__參數進去
app = Flask(__name__)


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


@app.route('/test/', methods=['POST'])  # 表示只容許POST請求
def home():
    print(request)  # request對象
    print(request.method)
    print(request.form)
    print(request.form['user'])
    print(request.form.get('pwd'))
    print(request.form.keys())
    for i in request.form.keys():
        print(i)
    return 'ok'


if __name__ == '__main__':
    # 這裏面的端口咱們是能夠本身設置的,我這裏就沒有設置了仍是默認的5000
    # debug=True表示啓動debug模式。當代碼有改動時,Flask會自動加載,無序重啓!默認是關閉的
    app.run(debug=True)  # 啓動Flask服務

 

重啓後再次訪問login而後輸入用戶名和密碼都是admin,

控制檯的輸出爲

<Request 'http://127.0.0.1:5000/test/' [POST]>
POST
ImmutableMultiDict([('user', 'admin'), ('pwd', 'admin')])
admin
admin
<dict_keyiterator object at 0x00000252AD6A0F48>
user
pwd

 

 上面的@app.route('/test/', methods=['POST'])

 後面的methods後面是列表,這個表示能夠有多個值,因此咱們想要容許什麼的請求就在這裏寫上就好。

request.form

 上面咱們Form表單提交的數據咱們能夠經過request.form拿到提交的數據。

print(request.form)  # ImmutableMultiDict([('user', 'xiao'), ('pwd', '123')])
# ImmutableMultiDict 它看起來像是的Dict 就用Dict的方法取值試一下吧
print(request.form["user"])  # admin
print(request.form.get("pwd"))  # admin
# 看來所有才對了, ImmutableMultiDict 彷佛就是個字典,再來玩一玩它
print(list(request.form.keys()))  # ['user', 'pwd'] 看來是又纔對了
#若是以上全部的方法你都以爲用的不爽的話
req_dict = dict(request.form)
print(req_dict)  # 若是你以爲用字典更爽的話,也能夠轉成字典操做(這裏有坑)

request.args

request.args中保存的是url中傳遞的參數

修改後端的GET

#!/usr/bin/env python
# -*-coding:utf-8-*-
from flask import Flask  # 導入Flask類
from flask import render_template  # 導入flask中的render_template
from flask import request

# 實例化一個Flask對象,傳遞__name__參數進去
app = Flask(__name__)


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


@app.route('/test/', methods=['POST', 'GET'])  # 表示只容許POST請求
def home():
    print(request.args)
    print(request.args['id'])
    print(request.args.get('age'))
    print(list(request.args.keys()))
    print(list(request.args.values()))
    req_dic = dict(request.args)
    print(req_dic)
    # print(request)  # request對象
    # print(request.method)
    # print(request.form)
    # print(request.form['user'])
    # print(request.form.get('pwd'))
    # print(request.form.keys())
    # for i in request.form.keys():
    #     print(i)
    return 'ok'


if __name__ == '__main__':
    # 這裏面的端口咱們是能夠本身設置的,我這裏就沒有設置了仍是默認的5000
    # debug=True表示啓動debug模式。當代碼有改動時,Flask會自動加載,無序重啓!默認是關閉的
    app.run(debug=True)  # 啓動Flask服務

而後在url地址欄輸入下面的url

http://127.0.0.1:5000/test/?id=13&age=28

獲得以下頁面

控制檯咱們獲得的輸出是

ImmutableMultiDict([('id', '13'), ('age', '28')])
13
28
['id', 'age']
['13', '28']
{'id': ['13'], 'age': ['28']}

 有上面的示列能夠看出request.form和request.args的區別

request.form是獲取form表單中的參數

request.args是獲取url中參數的

request.values

前端代碼改動部位爲黃色

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>歡迎登錄</h1>
<form action="/test?id=18&age=20" method="post">
    <p>
        <input type="text" name="user" placeholder="請輸入用戶名">
    </p>
    <p>
        <input type="password" name="pwd" placeholder="請輸入密碼">
    </p>
    <input type="submit" value="提交">
</form>
</body>
</html>

後端代碼爲

#!/usr/bin/env python
# -*-coding:utf-8-*-
from flask import Flask  # 導入Flask類
from flask import render_template  # 導入flask中的render_template
from flask import request

# 實例化一個Flask對象,傳遞__name__參數進去
app = Flask(__name__)


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


@app.route('/test', methods=['POST', 'GET'])  # 表示只容許POST和GET請求
def home():
    print(request.values)
    print(request.values.get('id'))
    print(request.values['user'])
    print(request.values.to_dict())
    # print(request.args)
    # print(request.args['id'])
    # print(request.args.get('age'))
    # print(list(request.args.keys()))
    # print(list(request.args.values()))
    # req_dic = dict(request.args)
    # print(req_dic)
    # print(request)  # request對象
    # print(request.method)
    # print(request.form)
    # print(request.form['user'])
    # print(request.form.get('pwd'))
    # print(request.form.keys())
    # for i in request.form.keys():
    #     print(i)
    return 'ok'


if __name__ == '__main__':
    # 這裏面的端口咱們是能夠本身設置的,我這裏就沒有設置了仍是默認的5000
    # debug=True表示啓動debug模式。當代碼有改動時,Flask會自動加載,無序重啓!默認是關閉的
    app.run(debug=True)  # 啓動Flask服務

訪問http://127.0.0.1:5000/login/輸入用戶名和密碼分別爲admin(這個用戶名和密碼隨便輸入)提交後在管理控制檯的輸出爲

CombinedMultiDict([ImmutableMultiDict([('id', '18'), ('age', '20')]), ImmutableMultiDict([('user', 'admin'), ('pwd', 'admin')])])
18
admin
{'user': 'admin', 'pwd': 'admin', 'id': '18', 'age': '20'}

上面咱們能夠看到只要是一個參數咱們均可以使用request.values來拿到

form表單的坑

若是咱們url和form表單中的key重名的話,form中的同名的key中value會被url中的value覆蓋

咱們只要修改前端

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>歡迎登錄</h1>
<form action="/test?id=18&user=20" method="post">
    <p>
        <input type="text" name="user" placeholder="請輸入用戶名">
    </p>
    <p>
        <input type="password" name="pwd" placeholder="請輸入密碼">
    </p>
    <input type="submit" value="提交">
</form>
</body>
</html>

  咱們仍是訪問登陸頁面輸入用戶名和密碼都是admin看看控制檯的輸出

CombinedMultiDict([ImmutableMultiDict([('id', '18'), ('user', '20')]), ImmutableMultiDict([('user', 'admin'), ('pwd', 'admin')])])
18
20
{'user': '20', 'pwd': 'admin', 'id': '18'}

咱們發現user變成了20,在這裏咱們輸入的是admin

若是URL和form表單中的key重名的話,form表單的同名的key的value值會被URL中同名的key的value值覆蓋。

request.cookies

request.cookies顧名思義就是讀取cookies中的信息

注意:這個要想讀取到cookies的信息就要開始瀏覽器的cookies

咱們修改上面的代碼中的home視圖函數

@app.route('/test', methods=['POST', 'GET']) 
def home():
    print(request.cookies)
    return 'ok'

 

咱們訪問 http://127.0.0.1:5000/login/而後輸入用戶名和密碼

在pycharm的控制檯咱們能夠看到

{'csrftoken': 'b0km4BAdzLjbMtXzfGTjv6z4tyac0DMK6tznTZzBjzkGEWA05tLgNyO9gKE2oQFn', 'sessionid': 'nh9jpx3dtnztxbkykof4f8fltbi8q85n'}

 

request.headers 

根據表面的意思就是用來獲取本次請求的請求頭

修改代碼中的home視圖函數

@app.route('/test', methods=['POST', 'GET']) 
def home():
    print(request.headers)
    return 'ok'

咱們在訪問前面的http://127.0.0.1:5000/login/而後輸入用戶名和密碼

在pycharm控制檯獲得的輸出爲

Host: 127.0.0.1:5000
Connection: keep-alive
Content-Length: 20
Cache-Control: max-age=0
Origin: http://127.0.0.1:5000
Upgrade-Insecure-Requests: 1
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Referer: http://127.0.0.1:5000/login/
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8
Cookie: csrftoken=b0km4BAdzLjbMtXzfGTjv6z4tyac0DMK6tznTZzBjzkGEWA05tLgNyO9gKE2oQFn; sessionid=nh9jpx3dtnztxbkykof4f8fltbi8q85n

request.data

這個就是處理不了的就變成字符串存在request.data裏面

request是基於mimetype進行處理的,這個若是不知道能夠去百度一下。

關於mimetype的類型以及字符串能夠看這個:http://www.w3school.com.cn/media/media_mimeref.asp

若是出現不屬於杉樹類型的描述,request就會將這些沒法處理的參數轉換爲JSON數據存入data中

修改代碼中home視圖函數

@app.route('/test', methods=['POST', 'GET'])  
def home():
    print(request.data)
    return 'ok'

再重複上面的操做咱們在pycharm的控制檯上能夠看到

b''

這裏顯示的是空,由上面的解釋咱們能夠知道由於咱們request可以處理,因此顯示爲空

request.files

若是遇到文件上傳的話,request.files 裏面存的是你上傳的文件,可是 Flask 在這個文件的操做中加了必定的封裝,讓操做變得極爲簡單

前端的html代碼爲:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h4>歡迎登錄</h4>
<form action="/test" method="post" enctype="multipart/form-data">
    <p>
        <input type="file" name="file">
    </p>
    <input type="submit" value="提交">
</form>
</body>
</html>

後端完整的代碼爲

#!/usr/bin/env python
# -*-coding:utf-8-*-
from flask import Flask  # 導入Flask類
from flask import render_template  # 導入flask中的render_template
from flask import request

# 實例化一個Flask對象,傳遞__name__參數進去
app = Flask(__name__)


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


@app.route('/test/', methods=['POST', 'GET'])  # 表示只容許POST和GET請求
def test():
    print(request.files)  # ImmutableMultiDict([('file', <FileStorage: 'test.txt' ('text/plain')>)])
    print(request.files["file"])  # <FileStorage: 'test.txt' ('text/plain')>
    my_file = request.files["file"]
    my_file.save("test3.txt")  # 保存文件,裏面能夠寫完整路徑+文件名
    return 'ok'


if __name__ == '__main__':
    # 這裏面的端口咱們是能夠本身設置的,我這裏就沒有設置了仍是默認的5000
    # debug=True表示啓動debug模式。當代碼有改動時,Flask會自動加載,無序重啓!默認是關閉的
    app.run(debug=True)  # 啓動Flask服務

訪問http://127.0.0.1:5000/login/

選擇一個文件上傳

點擊提交後

再看看咱們pycharm的控制檯的輸出

ImmutableMultiDict([('file', <FileStorage: 'test.txt' ('text/plain')>)])
<FileStorage: 'test.txt' ('text/plain')>

request.獲取各類路徑

關於下面的這些路徑咱們知道有這個就好

# 獲取當前的url路徑
print(request.path)  
# 當前url路徑的上一級路徑
print(request.script_root)  
# 當前url的所有路徑
print(request.url)  
# 當前url的路徑的上一級所有路徑
print(request.url_root)  

 request.json

若是在請求中咱們寫入"application/json" ,在使用request.json則返回json解析數據,不然返回None

 模板語言Jinja2

Jinja2

Flask中默認的模板語言就是Jinja2

咱們在後端定義幾個數據,用於傳遞到前端使用。

STUDENT = {'name': '溫碧霞', 'age': 18, 'gender': ''}

STUDENT_LIST = [
    {'name': '溫碧霞', 'age': 18, 'gender': ''},
    {'name': '胡歌', 'age': 22, 'gender': ''},
    {'name': '楊冪', 'age': 26, 'gender': ''}
]

STUDENT_DICT = {
    1: {'name': '溫碧霞', 'age': 18, 'gender': ''},
    2: {'name': '胡歌', 'age': 22, 'gender': ''},
    3: {'name': '楊冪', 'age': 26, 'gender': ''},
}

 下面來學習一下關於Jinja2模板中的一些流程控制:

for

{% for foo in val %}
{{ foo }}
{% endfor %}

if

{% if val0 %}

{% elif val %}
    
{% else %}
    
{% endif %}

下面咱們對上面的幾種數據分別進行傳遞,並在前端顯示成表格。

 字典

一、使用STUDENT字典傳遞至前端

目錄結構:

 

後端代碼

from flask import Flask  # 導入Flask類
from flask import render_template  # 導入flask中的render_template
from flask import request  # 導入flask中的request

app = Flask(__name__)

STUDENT = {'name': '溫碧霞', 'age': 18, 'gender': ''}

STUDENT_LIST = [
    {'name': '溫碧霞', 'age': 18, 'gender': ''},
    {'name': '胡歌', 'age': 22, 'gender': ''},
    {'name': '楊冪', 'age': 26, 'gender': ''}
]

STUDENT_DICT = {
    1: {'name': '溫碧霞', 'age': 18, 'gender': ''},
    2: {'name': '胡歌', 'age': 22, 'gender': ''},
    3: {'name': '楊冪', 'age': 26, 'gender': ''},
}


@app.route("/student")
def student():
    return render_template("student.html", student=STUDENT)


if __name__ == '__main__':
    app.run(debug=True)

 

前端student.html代碼(這個tudent.html在後端代碼統計目錄下的templates下)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h3>學生列表</h3>
<div>{{ student }}</div>
<table border="1px">
    <tr>
        <td>{{ student.name }}</td>
        <td>{{ student["age"] }}</td>
        <td>{{ student.get("gender") }}</td>
    </tr>
</table>
</body>
</html>

 

訪問http://127.0.0.1:5000/student能夠獲得

從這個例子中,能夠看出來,字典傳入前端Jinja2 模板語言中的取值操做, 與Python中的Dict操做極爲類似,而且多了一個student.name的對象操做

列表

目錄結構:

2. STUDENT_LIST 列表傳入前端Jinja2 模板的操做:

後端:

from flask import Flask  # 導入Flask類
from flask import render_template  # 導入flask中的render_template
from flask import request  # 導入flask中的request

app = Flask(__name__)

STUDENT = {'name': '溫碧霞', 'age': 18, 'gender': ''}

STUDENT_LIST = [
    {'name': '溫碧霞', 'age': 18, 'gender': ''},
    {'name': '胡歌', 'age': 22, 'gender': ''},
    {'name': '楊冪', 'age': 26, 'gender': ''}
]

STUDENT_DICT = {
    1: {'name': '溫碧霞', 'age': 18, 'gender': ''},
    2: {'name': '胡歌', 'age': 22, 'gender': ''},
    3: {'name': '楊冪', 'age': 26, 'gender': ''},
}


@app.route("/student_list")
def student_list():
    return render_template("student.html", student=STUDENT_LIST)


if __name__ == '__main__':
    app.run(debug=True)

後端:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h3>學生列表</h3>
<div>{{ student }}</div>
<table border="1px">
    {% for foo in student %}
    <tr>
        <td>{{ foo }}</td>
        <td>{{ foo.name }}</td>
        <td>{{ foo.get('age') }}</td>
        <td>{{ foo['gender'] }}</td>
    </tr>
    {% endfor %}
</table>
</body>
</html>

 訪問  http://127.0.0.1:5000/student_list

從上面咱們能夠看出,若是須要循環遍歷的話Jinja2給出的方案是

{% for foo in student %}
    <tr>
        <td>{{ foo }}</td>
    </tr>
{% endfor %}

 

 前端修改後:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h3>學生列表</h3>
<div>{{ student }}</div>
<table border="1px">
    {% for foo in student %}
        <tr>
            <td>{{ foo }}</td>
        </tr>
    {% endfor %}
</table>
</body>
</html>

 仍是訪問剛剛那個網址:http://127.0.0.1:5000/student_list

大字典

目錄結構和上面的同樣

後端:

from flask import Flask  # 導入Flask類
from flask import render_template  # 導入flask中的render_template
from flask import request  # 導入flask中的request

app = Flask(__name__)

STUDENT = {'name': '溫碧霞', 'age': 18, 'gender': ''}

STUDENT_LIST = [
    {'name': '溫碧霞', 'age': 18, 'gender': ''},
    {'name': '胡歌', 'age': 22, 'gender': ''},
    {'name': '楊冪', 'age': 26, 'gender': ''}
]

STUDENT_DICT = {
    1: {'name': '溫碧霞', 'age': 18, 'gender': ''},
    2: {'name': '胡歌', 'age': 22, 'gender': ''},
    3: {'name': '楊冪', 'age': 26, 'gender': ''},
}


@app.route("/student_dict")
def student_dict():
    return render_template("student.html", student=STUDENT_DICT)


if __name__ == '__main__':
    app.run(debug=True)

 

前端:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h3>學生列表</h3>
<div>{{ student }}</div>
<table border="1px">
    {% for foo in student %}
        <tr>
            <td>{{ foo }}</td>
            <td>{{ student.get(foo).name }}</td>
            <td>{{ student[foo].get("age") }}</td>
            <td>{{ student[foo]["gender"] }}</td>
        </tr>
    {% endfor %}
</table>
</body>
</html>

訪問:http://127.0.0.1:5000/student_dict

獲得如下

由上面能夠知道在遍歷字典的時候,foo其實就是字典的key值

數據集合

把全部的數據類型傳遞到前端

目錄結構仍是上面的同樣。

後端:

from flask import Flask  # 導入Flask類
from flask import render_template  # 導入flask中的render_template
from flask import request  # 導入flask中的request

app = Flask(__name__)

STUDENT = {'name': '溫碧霞', 'age': 18, 'gender': ''}

STUDENT_LIST = [
    {'name': '溫碧霞', 'age': 18, 'gender': ''},
    {'name': '胡歌', 'age': 22, 'gender': ''},
    {'name': '楊冪', 'age': 26, 'gender': ''}
]

STUDENT_DICT = {
    1: {'name': '溫碧霞', 'age': 18, 'gender': ''},
    2: {'name': '胡歌', 'age': 22, 'gender': ''},
    3: {'name': '楊冪', 'age': 26, 'gender': ''},
}


@app.route("/allstudent")
def all_student():
    return render_template("student.html", student=STUDENT,
                           student_list=STUDENT_LIST,
                           student_dict=STUDENT_DICT)


if __name__ == '__main__':
    app.run(debug=True)

 

前端代碼:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h3>學生列表</h3>
<div> _____________________________________</div>
Welcome to : student
<div>{{ student }}</div>
<table border="1px">
    <tr>
        <td>{{ student.name }}</td>
        <td>{{ student["age"] }}</td>
        <td>{{ student.get("gender") }}</td>
    </tr>
</table>
<div> _____________________________________</div>
Welcome to : student_list
<div>{{ student_list }}</div>
<table border="1xp">
    {% for foo in student_list %}
        <tr>
            <td>{{ foo }}</td>
            <td>{{ foo.name }}</td>
            <td>{{ foo.get("age") }}</td>
            <td>{{ foo["gender"] }}</td>
        </tr>
    {% endfor %}
</table>
<div> _____________________________________</div>
Welcome to : student_dict
<div>{{ student_dict }}</div>
<table border="1xp">
    {% for foo in student_dict %}
        <tr>
            <td>{{ foo }}</td>
            <td>{{ student_dict.get(foo).name }}</td>
            <td>{{ student_dict[foo].get("age") }}</td>
            <td>{{ student_dict[foo]["gender"] }}</td>
        </tr>
    {% endfor %}
</table>
</body>
</html>

 

 訪問網頁:http://127.0.0.1:5000/allstudent

從中咱們能夠看到,這個和Django同樣可也以傳遞多個關鍵字

 **{}字典

利用**{}字典的方式傳遞參數

目錄結構不變

前端代碼和上一個同樣

後端代碼

from flask import Flask  # 導入Flask類
from flask import render_template  # 導入flask中的render_template
from flask import request  # 導入flask中的request

app = Flask(__name__)

STUDENT = {'name': '溫碧霞', 'age': 18, 'gender': '女'}

STUDENT_LIST = [
    {'name': '溫碧霞', 'age': 18, 'gender': '女'},
    {'name': '胡歌', 'age': 22, 'gender': '男'},
    {'name': '楊冪', 'age': 26, 'gender': '女'}
]

STUDENT_DICT = {
    1: {'name': '溫碧霞', 'age': 18, 'gender': '女'},
    2: {'name': '胡歌', 'age': 22, 'gender': '男'},
    3: {'name': '楊冪', 'age': 26, 'gender': '女'},
}


@app.route("/allstudent")
def all_student():
    return render_template("student.html", **{"student": STUDENT,
                                              "student_list": STUDENT_LIST,
                                              "student_dict": STUDENT_DICT})


if __name__ == '__main__':
    app.run(debug=True)

 一樣訪問http://127.0.0.1:5000/allstudent

獲得的界面和上一個是同樣的

 Jinja2的高階用法之模板渲染

Jinja2 模板語言爲咱們提供了不少功能,下面介紹有關的功能及用法

安全相關的safe和MarkUp

沒錯這個和Django從後端傳遞html到前端,flask的safe和MarkUp和Django的safe和mark_safe對應

safe

後端代碼:

#!/usr/bin/env python
# -*-coding:utf-8-*-
from flask import Flask, session, redirect, request, url_for, render_template

app = Flask(__name__)


@app.route('/index/')
def index():
    txt = "<input type='text' />"
    return render_template('index.html', txt=txt)


if __name__ == '__main__':
    app.run(debug=True)

 

前端代碼:

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
{{ txt| safe }}
</body>
</html>

 

訪問:http://127.0.0.1:5000/index/

能夠看到頁面爲:

這樣咱們能夠知道經過前端使用{{ txt|safe }}標記爲後端的傳過來的爲安全的。

MarkUp

MarkUp和safe相反的寫在後端的處理方式

後端代碼爲:

#!/usr/bin/env python
# -*-coding:utf-8-*-
from flask import Flask, session, redirect, request, url_for, render_template, Markup

app = Flask(__name__)


@app.route('/index/')
def index():
    txt = Markup("<input type='text' />")
    return render_template('index.html', txt=txt)


if __name__ == '__main__':
    app.run(debug=True)

 

後端的代碼爲:

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
{{ txt }}
</body>
</html>

  上面的代碼結構index.html都是在後端代碼同級目錄下的templates目錄下的index.html

執行函數

Flask對於傳入的函數是不自動執行的,而Django是自動執行的

後端代碼:

#!/usr/bin/env python
# -*-coding:utf-8-*-
from flask import Flask, session, redirect, request, url_for, render_template, Markup

app = Flask(__name__)


def ab_sum(a, b):
    return a + b


@app.route('/index/')
def index():
    return render_template('index.html', func=ab_sum)


if __name__ == '__main__':
    app.run(debug=True)

 

前端代碼

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
{{ func }}
<br/>
{#後端的函數須要傳如2個參數#}
{{ func(1,9) }}
</body>
</html>

  

網址訪問:http://127.0.0.1:5000/index/

會出現的結果爲10。這裏咱們能夠看到咱們的Flask的在傳參方面很接近python。因此當咱們直接寫函數名的時候就會出現一個

 上面使咱們定義函數後把函數傳到後端,在這裏咱們能夠定義全局函數,不須要傳參的就可使用

後端代碼爲:

#!/usr/bin/env python
# -*-coding:utf-8-*-
from flask import Flask, session, redirect, request, url_for, render_template, Markup

app = Flask(__name__)


@app.template_global('ab')  # 定義全局模板函數(這個'ab'表示的全局模板定義的函數名若是不寫就是用咱們下面本身定義的函數名爲ab_sum)
def ab_sum(a, b):  # 這裏能夠傳遞多個參數前端使用和python使用同樣
    return a + b


@app.template_filter('abc')  # 定義全局模板函數(若是不寫就是abc_sum)
def abc_sum(a, b, c):  # 前端使用該函數的格式爲{{ 3|abc(6,9) }}第一個參數是在首位爲3
    return a + b + c


# 上面的'abc'表示在全局取名爲abc,調用的時候是{{ 3|abc(6,9) }},若是隻傳一個參數的時候咱們在後端能夠不用{{ 3|abc() }}或{{ 3|abc }}

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


if __name__ == '__main__':
    app.run(debug=True)

 

前端代碼:

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
{#函數#} {{ ab(1,9) }} <br/>
 {#過濾器#}
{{ 3|abc(6,9) }} 
</body>
</html>

  

兩個函數的調用方式不太同樣

尤爲是@app.template_filter() 它的調用方式比較特別,這是兩個Flask中的特殊裝飾器

 刷新頁面爲:

模板複用block

前端代碼:

layout.html

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
    <h1>模板</h1>
    {% block content %}{% endblock %}
</body>
</html>

login.html

{% extends "layout.html" %}
{% block content %}
    <h4>歡迎登錄</h4>
    <form>
        用戶名:<input type="text" name="user">
        密碼:<input type="text" name="pwd">
        <input type="submit" value="提交">
    </form>
{% endblock %}

index.html

{% extends "layou.html" %}
{% block content %}
    <h1>歡迎來到py3study.com</h1>
{% endblock %}

後端代碼:

from flask import Flask  # 導入Flask類
from flask import render_template  # 導入flask中的render_template

app = Flask(__name__)

@app.route("/login")
def login():
    return render_template("login.html")


@app.route("/home")
def home():
    return render_template("home.html")

if __name__ == '__main__':
    app.run("0.0.0.0", 5000, debug=True)

 

 訪問:http://127.0.0.1:5000/login/

訪問:http://127.0.0.1:5000/home/

引用include

Jinja2模板語言的模塊引用 include

login.html的文件內容

<h4>歡迎登錄</h4>
<form>
    用戶名:<input type="text" name="user">
    密碼:<input type="text" name="pwd">
    <input type="submit" value="提交">
</form>

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>歡迎登陸</h1>
    {% include "login.html" %}

</body>
</html>

後端代碼:

#!/usr/bin/env python
# -*-coding:utf-8-*-
from flask import Flask, session, redirect, request, url_for, render_template, Markup

app = Flask(__name__)


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


if __name__ == '__main__':
    app.run(debug=True)

訪問:http://127.0.0.1:5000/index/

宏定義

前端

index.html 

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

    <h1>Welcome to My</h1>
    {#type_text接收2個參數name,type#}
    {% macro type_text(name,type) %}
    {#渲染2個參數#}
    <input type="{{ type }}" name="{{ name }}" value="{{ name }}">
    {% endmacro %}

    <h2>在下方是使用宏來生成input標籤</h2>
    {#執行宏定義#}
    {{ type_text("one","text") }}
    {{ type_text("two","text") }}

</body>
</html>

  後端代碼:

#!/usr/bin/env python
# -*-coding:utf-8-*-
from flask import Flask, session, redirect, request, url_for, render_template, Markup

app = Flask(__name__)


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


if __name__ == '__main__':
    app.run(debug=True)

 訪問:http://127.0.0.1:5000/index/

宏定義通常狀況下不多應用到,可是要知道有這麼個概念

 

配置文件

flask是一個很是靈活且短小精悍的web框架。

flask有一個叫作配置的東西,先展現一下這個東東。

代碼:

#!/usr/bin/env python
# -*-coding:utf-8-*-
from flask import Flask, session, redirect, request, url_for, render_template, Markup

app = Flask(__name__)


@app.route("/login/")
def login():
    return render_template("login.html")


@app.route("/home/")
def home():
    return render_template("home.html")


if __name__ == '__main__':
    app.run(debug=True)

上面的代碼表示當咱們的代碼發生變化後會自動重啓Flask程序。

Flask的配置就是在 app.config 中添加一個鍵值對,可是你存進去的鍵必須是config中應該存在的,若是再也不存在的話,它會默認無用,就這麼放着

config中有多少有用的key 呢?

{
    'DEBUG': False,  # 是否開啓Debug模式
    'TESTING': False,  # 是否開啓測試模式
    'PROPAGATE_EXCEPTIONS': None,  # 異常傳播(是否在控制檯打印LOG) 當Debug或者testing開啓後,自動爲True
    'PRESERVE_CONTEXT_ON_EXCEPTION': None,  # 一兩句話說不清楚,通常不用它
    'SECRET_KEY': None,  # 以前遇到過,在啓用Session的時候,必定要有它
    'PERMANENT_SESSION_LIFETIME': 31,  # days , Session的生命週期(天)默認31天
    'USE_X_SENDFILE': False,  # 是否棄用 x_sendfile
    'LOGGER_NAME': None,  # 日誌記錄器的名稱
    'LOGGER_HANDLER_POLICY': 'always',
    'SERVER_NAME': None,  # 服務訪問域名
    'APPLICATION_ROOT': None,  # 項目的完整路徑
    'SESSION_COOKIE_NAME': 'session',  # 在cookies中存放session加密字符串的名字
    'SESSION_COOKIE_DOMAIN': None,  # 在哪一個域名下會產生session記錄在cookies中
    'SESSION_COOKIE_PATH': None,  # cookies的路徑
    'SESSION_COOKIE_HTTPONLY': True,  # 控制 cookie 是否應被設置 httponly 的標誌,
    'SESSION_COOKIE_SECURE': False,  # 控制 cookie 是否應被設置安全標誌
    'SESSION_REFRESH_EACH_REQUEST': True,  # 這個標誌控制永久會話如何刷新
    'MAX_CONTENT_LENGTH': None,  # 若是設置爲字節數, Flask 會拒絕內容長度大於此值的請求進入,並返回一個 413 狀態碼
    'SEND_FILE_MAX_AGE_DEFAULT': 12,  # hours 默認緩存控制的最大期限
    'TRAP_BAD_REQUEST_ERRORS': False,
    # 若是這個值被設置爲 True ,Flask不會執行 HTTP 異常的錯誤處理,而是像對待其它異常同樣,
    # 經過異常棧讓它冒泡地拋出。這對於須要找出 HTTP 異常源頭的可怕調試情形是有用的。
    'TRAP_HTTP_EXCEPTIONS': False,
    # Werkzeug 處理請求中的特定數據的內部數據結構會拋出一樣也是「錯誤的請求」異常的特殊的 key errors 。
    # 一樣地,爲了保持一致,許多操做能夠顯式地拋出 BadRequest 異常。
    # 由於在調試中,你但願準確地找出異常的緣由,這個設置用於在這些情形下調試。
    # 若是這個值被設置爲 True ,你只會獲得常規的回溯。
    'EXPLAIN_TEMPLATE_LOADING': False,
    'PREFERRED_URL_SCHEME': 'http',  # 生成URL的時候若是沒有可用的 URL 模式話將使用這個值
    'JSON_AS_ASCII': True,
    # 默認狀況下 Flask 使用 ascii 編碼來序列化對象。若是這個值被設置爲 False ,
    # Flask不會將其編碼爲 ASCII,而且按原樣輸出,返回它的 unicode 字符串。
    # 好比 jsonfiy 會自動地採用 utf-8 來編碼它而後才進行傳輸。
    'JSON_SORT_KEYS': True,
    #默認狀況下 Flask 按照 JSON 對象的鍵的順序來序來序列化它。
    # 這樣作是爲了確保鍵的順序不會受到字典的哈希種子的影響,從而返回的值每次都是一致的,不會形成無用的額外 HTTP 緩存。
    # 你能夠經過修改這個配置的值來覆蓋默認的操做。但這是不被推薦的作法由於這個默認的行爲可能會給你在性能的代價上帶來改善。
    'JSONIFY_PRETTYPRINT_REGULAR': True,
    'JSONIFY_MIMETYPE': 'application/json',
    'TEMPLATES_AUTO_RELOAD': None,
}

以上這些Key,均可以被改寫,固然他們也都是有默認值存在的,若是沒有特殊狀況,不要改寫它的默認值。

修改配置的方式

方式一:

向上面那樣直接修改

app.config["DEBUG"] = True

 

方式二:

類的導入

首先要建立一個setting.py的文件。

from datetime import timedelta


class Config(object):
    DEBUG = False
    TESTING = False
    SECRET_KEY = "asdfasdfas23"
    DATABASE_URI = 'sqlite://:memory:'

    SESSION_COOKIE_NAME = 'session'
    SESSION_COOKIE_DOMAIN = None
    SESSION_COOKIE_PATH = None
    SESSION_COOKIE_HTTPONLY = True
    SESSION_COOKIE_SECURE = False
    SESSION_REFRESH_EACH_REQUEST = True
    PERMANENT_SESSION_LIFETIME = timedelta(hours=1)


class ProductionConfig(Config):
    DATABASE_URI = 'mysql://user@localhost/foo'


class DevelopmentConfig(Config):
    DEBUG = True


class TestingConfig(Config):
    TESTING = True

 

上面寫了多個就是爲了咱們在實際中切換環境配合不一樣的環境

在flask程序中

from flask import Flask
app = Flask(__name__) # 應用配置類 

app.config.from_object("settings.DevelopmentConfig")

if __name__ == '__main__':
  app.run()

 

或者:

from flask import Flask
# 導入自定義配置文件的配置類
import setting
app = Flask(__name__) # 應用配置類 

app.config.from_object(settings.DevelopmentConfig) 

if __name__ == '__main__': 
  app.run()

 

關於如何給一個 路由加上一個登陸認證

方式一:

後端代碼:

#!/usr/bin/env python
# -*-coding:utf-8-*-
from flask import Flask, render_template, request, session, redirect

app = Flask(__name__)
# app.config['SESSION_COOKIE_NAME'] = 'session'
app.config['SECRET_KEY'] = 'lkjhgffddda'  # 使用seesion這個必定要設置,上面關於參數也寫了緣由。


@app.route('/login/', methods=['GET', 'POST'])
def login():
    if request.method == 'GET':
        return render_template('login.html')
    user = request.form.get('user')
    pwd = request.form.get('pwd')
    if user == 'qwe' and pwd == 'qwe':
        session['user'] = user
        return redirect('/index/')
    return render_template('login.html', error='用戶名或密碼錯誤')


@app.route('/index/')
def index():
    user = session.get('user')
    if not user:
        return redirect('/login/')
    return 'ok'


if __name__ == '__main__':
    app.run()

 

login.html

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
    <h1>用戶登陸</h1>
    <form method="post">
        <input type="text" name="user">
        <input type="password" name="pwd">
        <input type="submit" value="提交">{{error}}
    </form>
</body>
</html>

 

方式二:

後端代碼

#!/usr/bin/env python
# -*-coding:utf-8-*-
from flask import Flask, render_template, request, session, redirect, url_for

app = Flask(__name__)
# app.config['SESSION_COOKIE_NAME'] = 'session'
app.config['SECRET_KEY'] = 'lkjhgffddda'

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('/login/', methods=['GET', 'POST'])
def login():
    if request.method == 'GET':
        return render_template('login.html')
    user = request.form.get('user')
    pwd = request.form.get('pwd')
    if user == 'qwe' and pwd == 'qwe':
        session['user'] = user
        return redirect('/index/')
    return render_template('login.html', error='用戶名或密碼錯誤')


@app.route('/index/')
@auth
def index():
    return 'ok'


if __name__ == '__main__':
    app.run(debug=True)

應用場景:比較少的函數中須要額外添加功能。

前端代碼不變

方式三:

後端代碼:

#!/usr/bin/env python
# -*-coding:utf-8-*-
from flask import Flask, render_template, request, session, redirect, url_for

app = Flask(__name__)
# app.config['SESSION_COOKIE_NAME'] = 'session'
app.config['SECRET_KEY'] = 'lkjhgffddda'

# 這個每當請求進來後第一個走的就是這個函數。相似於Django的中間件
@app.before_request def xxxxxx(): if request.path == '/login/': return None if session.get('user'): return None return redirect('/login/') @app.route('/login/', methods=['GET', 'POST']) def login(): if request.method == 'GET': return render_template('login.html') user = request.form.get('user') pwd = request.form.get('pwd') if user == 'qwe' and pwd == 'qwe': session['user'] = user return redirect('/index/') return render_template('login.html', error='用戶名或密碼錯誤') @app.route('/index/') def index(): return 'ok' if __name__ == '__main__': app.run(debug=True)

前端代碼不變。上面的login.html都在後端代碼同級目錄下的templates目錄下面建立的。

 下面來講一說session

當請求剛到來:flask讀取cookie中session對應的值:eyJrMiI6NDU2LCJ1c2VyIjoib2xkYm95,將該值解密並反序列化成字典,放入內存以便視圖函數使用。

當請求結束時,flask會讀取內存中字典的值,進行序列化+加密,寫入到用戶cookie中。

閃現

在session中存儲一個數據,讀取時經過pop將數據移除。
from flask import Flask,flash,get_flashed_messages

後端代碼

#!/usr/bin/env python
# -*-coding:utf-8-*-
from flask import Flask,flash,get_flashed_messages
app = Flask(__name__)


@app.route('/page1/')
def page1():
    # session['uuuuu'] = 123
    flash('臨時數據存儲', 'error')
    flash('sdfsdf234234', 'error')
    flash('adasdfasdf', 'info')

    return "Session"


@app.route('/page2/')
def page2():
    # print(session['uuuuu'])
    # del session['uuuuu']
    # session.pop('uuuuu')
    print(get_flashed_messages(category_filter=['error']))
    return "Session"


if __name__ == '__main__':
    app.run(debug=True)

咱們先訪問:http://127.0.0.1:5000/page1/至關於把數據放到進去

在訪問http://127.0.0.1:5000/page2/至關於取數據,

咱們在pycharm控制檯看到

['臨時數據存儲','sdfsdf234234']

上面取數據的的時候,只取error的數據因此看到上面的結果。

相關文章
相關標籤/搜索