1. 程式人生 > >python之初識Flask

python之初識Flask

一、初識Flask

Python三大主流Web框架對比

1、三大框架的特點

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

2、三大框架的優缺點 

  • Django 通常用於大型Web應用由於內建元件足夠強大所以使用Django開發可以一氣呵成
  • Tornado 通常用於API後端應用,遊戲服務後臺,其內部實現的非同步非阻塞真是穩得一批
  • Flask 通常應用於小型應用和快速構建應用,其強大的三方庫,足以支撐一個大型的Web應用
  • Django 優點是大而全,缺點也就暴露出來了,這麼多的資源一次性全部載入,肯定會造成一部分的資源浪費
  • Tornado 優點是非同步,缺點是乾淨,連個Session都不支援
  • Flask 優點是精悍簡單,缺點是元件大都來自第三方等

關於上面的總結

Django:

  優點:

    大而全,admin,models,Form,中介軟體,session

    一個框架解決所有問題

  缺點:

    一旦啟動,所有資源全部載入,用不到的,浪費了

    太大了,結構複雜

    所有的元件,全部由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 %}

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

 字典

1、使用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