日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

flask使用操作指南

 刮骨劍 2019-06-26

1. flask介紹

Flask是一個(gè)基于Python實(shí)現(xiàn)的web開(kāi)發(fā)的'微'框架

中文文檔地址

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

flask流行的主要原因:

a)有非常齊全的官方文檔,上手非常方便

b) 有非常好的拓展機(jī)制和第三方的拓展環(huán)境,工作中常見(jiàn)的軟件都有對(duì)應(yīng)的拓展,自己動(dòng)手實(shí)現(xiàn)拓展也很容易

c) 微型框架的形式給了開(kāi)發(fā)者更大的選擇空間

2. 安裝flask

2.1虛擬環(huán)境搭建

virtualenv --no-site-packages falskenv
  
激活windows下虛擬環(huán)境cd Scripts
activate

2.2 安裝

pip install flask

3. 基于flask的最小的應(yīng)用

創(chuàng)建hello.py文件

from flask import Flask

app = Flask(__name__)@app.route('/')def gello_world():
    return 'Hello World'if __name__ == '__main__':

    app.run()

運(yùn)行:python hello.py

3.1 初始化

from flask import Flask

app = Flask(__name__)

Flask類構(gòu)造函數(shù)唯一需要的參數(shù)就是應(yīng)用程序的主模塊或包。對(duì)于大多數(shù)應(yīng)用程序,Python的__name__變量就是那個(gè)正確的、你需要傳遞的值。Flask使用這個(gè)參數(shù)來(lái)確定應(yīng)用程序的根目錄,這樣以后可以相對(duì)這個(gè)路徑來(lái)找到資源文件。

3.2 路由

@app.route('/')

客戶端例如web瀏覽器發(fā)送 請(qǐng)求 給web服務(wù),進(jìn)而將它們發(fā)送給Flask應(yīng)用程序?qū)嵗?。?yīng)用程序?qū)嵗枰缹?duì)于各個(gè)URL請(qǐng)求需要運(yùn)行哪些代碼,所以它給Python函數(shù)建立了一個(gè)URLs映射。這些在URL和函數(shù)之間建立聯(lián)系的操作被稱之為 路由 。

在Flask應(yīng)程序中定義路由的最便捷的方式是通過(guò)顯示定義在應(yīng)用程序?qū)嵗系腶pp.route裝飾器,注冊(cè)被裝飾的函數(shù)來(lái)作為一個(gè)路由。

3.3 視圖函數(shù)

在上一個(gè)示例給應(yīng)用程序的根URL注冊(cè)gello_world()函數(shù)作為事件的處理程序。如果這個(gè)應(yīng)用程序被部署在服務(wù)器上并綁定了 www. 域名,然后在你的瀏覽器地址欄中輸入 http://www. 將觸發(fā)gello_world()來(lái)運(yùn)行服務(wù)??蛻舳私邮盏降倪@個(gè)函數(shù)的返回值被稱為 響應(yīng) 。如果客戶端是web瀏覽器,響應(yīng)則是顯示給用戶的文檔。

類似于gello_world()的函數(shù)被稱作 視圖函數(shù) 。

3.4 動(dòng)態(tài)名稱組件路由

你的Facebook個(gè)人信息頁(yè)的URL是 http://www./<username> ,所以你的用戶名是它的一部分。Flask在路由裝飾器中使用特殊的語(yǔ)法支持這些類型的URLs。下面的示例定義了一個(gè)擁有動(dòng)態(tài)名稱組件的路由:

@app.route('/hello/<name>')def gello_world(name):    return 'Hello World %s' % name

用尖括號(hào)括起來(lái)的部分是動(dòng)態(tài)的部分,所以任何URLs匹配到靜態(tài)部分都將映射到這個(gè)路由。當(dāng)視圖函數(shù)被調(diào)用,F(xiàn)lask發(fā)送動(dòng)態(tài)組件作為一個(gè)參數(shù)。在前面的示例的視圖函數(shù)中,這個(gè)參數(shù)是用于生成一個(gè)個(gè)性的問(wèn)候作為響應(yīng)。

在路由中動(dòng)態(tài)組件默認(rèn)為字符串,但是可以定義為其他類型。例如,路由/user/<int:id>只匹配有一個(gè)整數(shù)在id動(dòng)態(tài)段的URLs。Flask路由支持int、float、string、path

路由匹配的規(guī)則
1.<id> :默認(rèn)接受的類型是str
2.<string:id> :指定id的類型為str
3.<int:id> :指定的id類型是整性
4.<float:id> : 指定id的類型為浮點(diǎn)數(shù)(四舍五入,且不能接收整數(shù)類型)
5.<path:path1> : 指定接收的path為url中的路徑

如下:

  @blue.route('/get_id/<id>/')def get_id(id):    #匹配str類型的id值
    return 'id: %s' % id


@blue.route('/get_int_id/<int:id>/')def get_int_id(id):    #匹配int類型的id值
    return 'id:%d' % id


@blue.route('/get_float/<float:uid>/')def get_float(uid):    #匹配float類型的值,不能匹配int類型(四舍五入)
    return 'uid:%.2f' %uid


@blue.route('/get_path/<path:upath>/')def get_path(upath):    #匹配url路徑
    return 'path:%s' % upath 

3.5 服務(wù)啟動(dòng)

if __name__ == '__main__':

    app.run()

注意: __name__ == '__main__'在此處使用是用于確保web服務(wù)已經(jīng)啟動(dòng)當(dāng)腳本被立即執(zhí)行。當(dāng)腳本被另一個(gè)腳本導(dǎo)入,它被看做父腳本將啟動(dòng)不同的服務(wù),所以app.run()調(diào)用會(huì)被跳過(guò)。

一旦服務(wù)啟動(dòng),它將進(jìn)入循環(huán)等待請(qǐng)求并為之服務(wù)。這個(gè)循環(huán)持續(xù)到應(yīng)用程序停止,例如通過(guò)按下Ctrl-C。

有幾個(gè)選項(xiàng)參數(shù)可以給app.run()配置web服務(wù)的操作模式。在開(kāi)發(fā)期間,可以很方便的開(kāi)啟debug模式,將激活 debugger 和 reloader 。這樣做是通過(guò)傳遞debug為T(mén)rue來(lái)實(shí)現(xiàn)的。

app.run(host='0.0.0.0',port=8080,debug=True)

run()中參數(shù)有如下:

debug 是否開(kāi)啟調(diào)試模式,開(kāi)啟后修改python的代碼會(huì)自動(dòng)重啟port 啟動(dòng)指定服務(wù)器的端口號(hào)host主機(jī),默認(rèn)是127.0.0.1

4. 修改啟動(dòng)方式,使用命令行參數(shù)啟動(dòng)服務(wù)

4.1 安裝插件

pip install flask-script

調(diào)整代碼
manager = Manager(app=‘自定義的flask對(duì)象’)

啟動(dòng)的地方
manager.run()

4.2 啟動(dòng)命令

python hellow.py runserver -h 地址 -p 端口 -d -r

其中:-h表示地址。-p表示端口。-d表示debug模式。-r表示自動(dòng)重啟

如:manager.run(python xx.py runserver -h 0.0.0.0 -p 8080 -d)

5. route規(guī)則

5.1 規(guī)則

寫(xiě)法:<converter:variable_name>

converter類型:

string 字符串int 整形float 浮點(diǎn)型
path 接受路徑,接收的時(shí)候是str,/也當(dāng)做字符串的一個(gè)字符
uuid 只接受uuid字符串
any 可以同時(shí)指定多種路徑,進(jìn)行限定

例子:

@app.route('/helloint/<int:id>/')@app.route('/getfloat/<float:price>/')@app.route('/getstr/<string:name>/',methods=['GET', 'POST'])@app.route('/getpath/<path:url_path>/')@app.route('/getbyuuid/<uuid:uu>/',methods=['GET', 'POST'])

實(shí)現(xiàn)對(duì)應(yīng)的視圖函數(shù):

@blue.route('/hello/<name>/')def hello_man(name):
    print(type(name))    return 'hello name:%s type:%s' % (name, type(name))


@blue.route('/helloint/<int:id>/')def hello_int(id):
    print(id)
    print(type(id))    return 'hello int: %s' % (id)


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


@blue.route('/getfloat/<float:price>/')def hello_float(price):    return 'float: %s' % price


@blue.route('/getstr/<string:name>/')def hello_name(name):    return 'hello name: %s' % name


@blue.route('/getpath/<path:url_path>/')def hello_path(url_path):    return 'path: %s' % url_path


@blue.route('/getuuid/')def gello_get_uuid():
    a = uuid.uuid4()    return str(a)


@blue.route('/getbyuuid/<uuid:uu>/')def hello_uuid(uu):    return 'uu:%s' % uu

5.2 methods請(qǐng)求方法

常用的請(qǐng)求類型有如下幾種

GET : 獲取
POST : 創(chuàng)建
PUT : 修改(全部屬性都修改)
DELETE : 刪除
PATCH : 修改(修改部分屬性)

定義url的請(qǐng)求類型:

@blue.route('/getrequest/', methods=['GET', 'POST'])

flask使用操作指南2


1. 什么是藍(lán)圖

在Flask項(xiàng)目中可以用Blueprint(藍(lán)圖)實(shí)現(xiàn)模塊化的應(yīng)用,使用藍(lán)圖可以讓?xiě)?yīng)用層次更清晰,開(kāi)發(fā)者更容易去維護(hù)和開(kāi)發(fā)項(xiàng)目。藍(lán)圖將作用于相同的URL前綴的請(qǐng)求地址,將具有相同前綴的請(qǐng)求都放在一個(gè)模塊中,這樣查找問(wèn)題,一看路由就很快的可以找到對(duì)應(yīng)的視圖,并解決問(wèn)題了。

2. 使用藍(lán)圖

2.1 安裝

pip install flask_blueprint

2.2 實(shí)例化藍(lán)圖應(yīng)用

blue = Blueprint(‘first’,_ _name_ _)

注意:Blueprint中傳入了兩個(gè)參數(shù),第一個(gè)是藍(lán)圖的名稱,第二個(gè)是藍(lán)圖所在的包或模塊,_ name _代表當(dāng)前模塊名或者包名

2.3 注冊(cè)

app = Flask(_ _name_ _)

app.register_blueprint(blue, url_prefix='/user')

注意:第一個(gè)參數(shù)即我們定義初始化定義的藍(lán)圖對(duì)象,第二個(gè)參數(shù)url_prefix表示該藍(lán)圖下,所有的url請(qǐng)求必須以/user開(kāi)始。這樣對(duì)一個(gè)模塊的url可以很好的進(jìn)行統(tǒng)一管理

3 使用藍(lán)圖

修改視圖上的裝飾器,修改為@blue.router(‘/’)

@blue.route('/', methods=['GET', 'POST'])def hello():    # 視圖函數(shù)
    return 'Hello World'

注意:該方法對(duì)應(yīng)的url為127.0.0.1:5000/user/

4 url_for反向解析

語(yǔ)法:

url_for('藍(lán)圖中定義的第一個(gè)參數(shù).函數(shù)名', 參數(shù)名=value)

定義跳轉(zhuǎn):

from flask import url_for, redirect@blue.route('/redirect/')def make_redirect():
    # 第一種方法
    return redirect('/hello/index/')    # 第二種方法
    return redirect(url_for('first.index'))

flask使用操作指南3


1. 請(qǐng)求request

服務(wù)端在接收到客戶端的請(qǐng)求后,會(huì)自動(dòng)創(chuàng)建Request對(duì)象

由Flask框架創(chuàng)建,Requesy對(duì)象不可修改

屬性:

url:完整的請(qǐng)求地址

base_url:去掉GET參數(shù)的url

host_url:只有主機(jī)和端口號(hào)的url

path:路由中的路徑

method:請(qǐng)求方法

remote_addr:請(qǐng)求的客戶端的地址

args:GET請(qǐng)求參數(shù)

form:POST請(qǐng)求參數(shù)

files:文件上傳

headers:請(qǐng)求頭

cookies:請(qǐng)求中的cookie

1.1 args-->GET請(qǐng)求參數(shù)包裝

a)args是get請(qǐng)求參數(shù)的包裝,args是一個(gè)ImmutableMultiDict對(duì)象,類字典結(jié)構(gòu)對(duì)象

b)數(shù)據(jù)存儲(chǔ)也是key-value

1.2 form-->POST請(qǐng)求參數(shù)包裝

a)form是post請(qǐng)求參數(shù)的包裝,args是一個(gè)ImmutableMultiDict對(duì)象,類字典結(jié)構(gòu)對(duì)象

b)數(shù)據(jù)存儲(chǔ)也是key-value

重點(diǎn):ImmutableMultiDict是類似字典的數(shù)據(jù)結(jié)構(gòu),但是與字典的區(qū)別是,<font style="color:red; font-weight:bold;">可以存在相同的鍵</font>。

在ImmutableMultiDict中獲取數(shù)據(jù)的方式,dict['key']或者dict.get('key')或者dict.getlist('key')

image.png

2. 響應(yīng)Response

Response是由開(kāi)發(fā)者自己創(chuàng)建的

創(chuàng)建方法:

from flask import make_response

make_response創(chuàng)建一個(gè)響應(yīng),是一個(gè)真正的Response對(duì)象

狀態(tài)碼:

格式:make_reponse(data,code),其中data是返回的數(shù)據(jù)內(nèi)容,code是狀態(tài)碼

a)直接將內(nèi)容當(dāng)做make_response的第一個(gè)參數(shù),第二個(gè)參數(shù)直接寫(xiě)返回的狀態(tài)碼

b)直接在render后加返回的狀態(tài)碼

例子1:

定義一個(gè)獲取GET請(qǐng)求的request的方法,并將返回成功的請(qǐng)求的狀態(tài)碼修改為200

@blue.route('/getrequest/', methods=['GET'])def get_request():

    print(request)    return '獲取request', 200

例子2:

返回response響應(yīng),并添加返回結(jié)果的狀態(tài)碼200

@blue.route('/getresponse/')def get_response():
    response = make_response('<h2>我是響應(yīng)</h2>', 500)    return response

或者:

@blue.route('/getresponse/', methods=['GET'])def get_user_response():
    login_html = render_template('login.html')
    res = make_response(login_html, 200)    return res

3. 重定向/反向解析

url_for('藍(lán)圖定義的名稱.方法名')

例子1:

定義跳轉(zhuǎn)方法,跳轉(zhuǎn)到get_response的方法上

@blue.route('/getredirect/')def get_redirect():    return redirect('getresponse')

例子2:

使用url_for反向解析

from flask import redirect, url_for@blue.route('/getredirect/')def get_redirect():

    return redirect(url_for('first.get_response'))

4. 終止/異常捕獲

自動(dòng)拋出異常:abort(狀態(tài)碼)

捕獲異常處理:errorhandler(狀態(tài)碼),定義的函數(shù)中要包含一個(gè)參數(shù),用于接收異常信息

4.1 定義終止程序

@blue.route('/make_abort/')def get_abort():
    abort(400)    return '終止'

4.2 捕獲定義的異常

@blue.errorhandler(400)def handler(exception):

    return '捕獲到異常信息:%s' % exception

flask使用操作指南之session/cookie


前言

訪問(wèn)者的標(biāo)識(shí)問(wèn)題服務(wù)器需要識(shí)別來(lái)自同一訪問(wèn)者的請(qǐng)求。這主要是通過(guò)瀏覽器的cookie實(shí)現(xiàn)的。 訪問(wèn)者在第一次訪問(wèn)服務(wù)器時(shí),服務(wù)器在其cookie中設(shè)置一個(gè)唯一的ID號(hào)——會(huì)話ID(session)。 這樣,訪問(wèn)者后續(xù)對(duì)服務(wù)器的訪問(wèn)頭中將自動(dòng)包含該信息,服務(wù)器通過(guò)這個(gè)ID號(hào),即可區(qū) 隔不同的訪問(wèn)者。

1. Cookie

概念:

a)客戶端會(huì)話技術(shù),瀏覽器的會(huì)話技術(shù)

b)數(shù)據(jù)全部存儲(chǔ)在客戶端中

c)存儲(chǔ)使用的鍵值對(duì)結(jié)構(gòu)進(jìn)行存儲(chǔ)

特性:
    支持過(guò)期時(shí)間
    默認(rèn)會(huì)自動(dòng)攜帶本網(wǎng)站的cookie
    不能跨域名
    不能跨瀏覽器

創(chuàng)建:

Cookie是通過(guò)服務(wù)器創(chuàng)建的Response來(lái)創(chuàng)建的

設(shè)置:set_cookie('key', value, max_ages='', expires='')

刪除, 有三種刪除方式
    
    1. 直接清空瀏覽器的cookie
    2. delete_cookie('key') 直接使用delete_cookie函數(shù)
    3. set_cookie('key','',expires=0) 重新設(shè)置key的值為空,過(guò)期時(shí)間為0

獲?。?/p>

在每次請(qǐng)求中,url都會(huì)向服務(wù)器傳遞Request,在request中可以獲取到cookie的信息

request.cookies.get('name')

例子1,設(shè)置cookie:

import datetime@blue.route('/setcookie/')def set_cookie():
    temp = render_template('index.html')
    response = make_response(temp)
    outdate=datetime.datetime.today() + datetime.timedelta(days=30)    # 設(shè)置cookie中的name的存在時(shí)長(zhǎng),設(shè)置為30天才過(guò)期  
    response.set_cookie('name','cocoococo',expires=outdate)    return response

例子2,刪除cookie中的值

@blue.route('/setcookie/')def set_cookie():
    temp = render_template('index.html')
    response = make_response(temp)    # 第一種方式,通過(guò)set_cookie去刪除
    response.set_cookie('name','',expires=0)    # 第二種方式,del_cookie刪除
    response.del_cookie('name')    return response

例子3,獲取cookie中的值

@blue.route('/getcookie/')  
def get_cookie():
    name=request.cookies.get('name')  
    return name

2. Session

flask-session是flask框架的session組件

該組件則將支持session保存到多個(gè)地方

如:

redis:保存數(shù)據(jù)的一種工具,五大類型。非關(guān)系型數(shù)據(jù)庫(kù)

memcached

mongodb

sqlalchmey:那數(shù)據(jù)存到數(shù)據(jù)庫(kù)表里面

2.1 安裝

pip install flask-session

如果指定存session的類型為redis的話,需要安裝redis

pip install redis

2.2 語(yǔ)法

設(shè)置session:

session['key'] = value

讀取session:

result = session['key'] :如果內(nèi)容不存在,將會(huì)報(bào)異常

result = session.get('key') :如果內(nèi)容不存在,將返回None

刪除session:

session.pop('key')

清空session中所有數(shù)據(jù):

session.clear()

2.2 使用

我們?cè)诔跏蓟募袆?chuàng)建一個(gè)方法,通過(guò)調(diào)用該方法來(lái)獲取到Flask的app對(duì)象

def create_app():
    app = Flask(__name__)    # SECRET_KEY 秘鑰
    app.config['SECRET_KEY'] = 'secret_key'
    # session類型為redis
    app.config['SESSION_TYPE'] = 'redis'
    # 添加前綴
    app.config['SESSION_KEY_PREFIX'] = 'flask'
    
    # 加載app的第一種方式
    se = Session()
    se.init_app(app=app)    #加載app的第二種方式
    Session(app=app)
    app.register_blueprint(blueprint=blue)    return app

2.3 案例

定義一個(gè)登陸的方法,post請(qǐng)求獲取到username,直接寫(xiě)入到redis中,并且在頁(yè)面中展示出redis中的username

a)需要先啟動(dòng)redis,開(kāi)啟redis-server,使用redis-cli進(jìn)入客戶端

b)定義方法

@blue.route('/login/', methods=['GET', 'POST'])def login():    if request.method == 'GET':
        username = session.get('username')        return render_template('login.html', username=username)    else:
        username = request.form.get('username')
        session['username'] = username        return redirect(url_for('first.login'))

c)定義模板

<body><h3>歡迎:{{ username }}</h3><form action="" method="POST">
    用戶名:<input type="text" name="username" placeholder="請(qǐng)輸入你的名字">
    <input type="submit" value="提交"></form></body>

d)redis中數(shù)據(jù)


image.png

注意:我們?cè)诙xapp.config的時(shí)候指定了SESSION_KEY_PREFIX為flask,表示存在session中的key都會(huì)加一個(gè)前綴名flask

e) cookie和session的聯(lián)系

image.png

訪問(wèn)者在第一次訪問(wèn)服務(wù)器時(shí),服務(wù)器在其cookie中設(shè)置一個(gè)唯一的ID號(hào)——會(huì)話ID(session)。 這樣,訪問(wèn)者后續(xù)對(duì)服務(wù)器的訪問(wèn)頭中將自動(dòng)包含該信息,服務(wù)器通過(guò)這個(gè)ID號(hào),即可區(qū) 隔不同的訪問(wèn)者。然后根據(jù)不同的訪問(wèn)者來(lái)獲取其中保存的value值信息。

flask使用操作指南之session實(shí)現(xiàn)登錄驗(yàn)證


功能描述

使用session實(shí)現(xiàn)用戶的模擬登陸功能。在前面已經(jīng)說(shuō)過(guò)了,在用戶第一次訪問(wèn)服務(wù)端的時(shí)候,在服務(wù)端的redis中會(huì)創(chuàng)建一個(gè)session值,在客戶端瀏覽器的cookies中也會(huì)創(chuàng)建一個(gè)session的值。該cookies中的session值和redis中的session值是一樣的,那么在往后的訪問(wèn)操作中,請(qǐng)求request都會(huì)傳遞給后端,后端在獲取到request的時(shí)候,其實(shí)就是獲取到了request.cookies中的session的值了,那么就可以做登錄的校驗(yàn)了。校驗(yàn)功能如下:

素材地址

1. 前端login.html頁(yè)面

登錄頁(yè)面就兩個(gè)輸入框,分別接收用戶名和密碼

  <dd class="user_icon">   <input type="text" name="username" placeholder="賬號(hào)" class="login_txtbx"/>
  </dd>
  <dd class="pwd_icon">   <input type="password" name="password" placeholder="密碼" class="login_txtbx"/>
  </dd>

2. 后端方法

模擬用戶的登錄,直接判斷用戶的名稱為妲己以及密碼為123123.如果驗(yàn)證成功,就向session中保存用戶的id值。如果沒(méi)有登錄成功的話,那就對(duì)session不做任何的處理,直接跳轉(zhuǎn)到登錄頁(yè)面上去。

@app_blue.route('/new_login/', methods=['GET', 'POST'])def new_login():    if request.method == 'GET':        return render_template('login.html')    else:
        username = request.form.get('username')
        password = request.form.get('password')        # 數(shù)據(jù)庫(kù)校驗(yàn),用戶密碼是否正確
        if username == '妲己' and password == '123123':
            session['user_id'] = 1
            return redirect((url_for('first.index')))        else:
            return redirect(url_for('first.new_login'))


@app_blue.route('/index/', methods=['GET'])
def index():
return render_template('index.html')

3. 裝飾器

使用裝飾器去裝飾我們的index()函數(shù),如果用戶登錄了,則session中有user_id的key,如果沒(méi)有登錄的話,session中是沒(méi)有user_id的key的。那么驗(yàn)證用戶是否登錄了,其實(shí)就是驗(yàn)證session的user_id

def is_login(func):    @wraps(func)
    def check_login(*args, **kwargs):
        if 'user_id' in session:            return func(*args, **kwargs)        else:            return redirect(url_for('first.new_login'))    return check_login

4. 修改index()函數(shù),使用裝飾器裝飾

@app_blue.route('/index/', methods=['GET'])
@is_logindef index():    return render_template('index.html')

flask使用操作指南之模板


1. jinja2

Flask中使用jinja2模板引擎

jinja2是由Flask作者開(kāi)發(fā),模仿Django的模板引擎

優(yōu)點(diǎn):

速度快,被廣泛使用

HTML設(shè)計(jì)和后端python分離

非常靈活,快速和安全

提供了控制,繼承等高級(jí)功能

2. 模板語(yǔ)法

2.1 模板語(yǔ)法主要分為兩種:變量和標(biāo)簽

模板中的變量:{{ var }}

視圖傳遞給模板的數(shù)據(jù)

前面定義出來(lái)的數(shù)據(jù)

變量不存在,默認(rèn)忽略

模板中的標(biāo)簽:{% tag %}

控制邏輯

使用外部表達(dá)式

創(chuàng)建變量

宏定義

2.2 結(jié)構(gòu)標(biāo)簽:

block

{% block xxx %}

{% endblock %}

塊操作
    父模板挖坑,子模板填坑

extends

{% extends ‘xxx.html’ %}

繼承以后保留塊中的內(nèi)容
{{ super() }}

挖坑繼承體現(xiàn)的化整為零的操作

macro

{% macro hello(name) %}    {{ name }}

{% endmacro %}

宏定義,可以在模板中定義函數(shù),在其他地方調(diào)用

宏定義可導(dǎo)入

{% from 'xxx' import xxx %}

例子1:

在index.html中定義macro標(biāo)簽,定義一個(gè)方法,然后去調(diào)用方法,結(jié)果是展示商品的id和商品名稱

{% macro show_goods(id, name) %}
    商品id:{{ id }}
    商品名稱:{{ name }}
{% endmacro %}

{{ show_goods('1', '娃哈哈') }}
<br>
{{ show_goods('2', '雪碧') }}

例子2:

在index.html頁(yè)面中定義一個(gè)say()方法,然后解析該方法:

{% macro say() %}    <h3>今天天氣氣溫回升</h3>
    <h3>適合去游泳</h3>
    <h3>適合去郊游</h3>{% endmacro %}

{{ say() }}

例子3:

定義一個(gè)function.html中定義一個(gè)方法:

{% macro create_user(name) %}
    創(chuàng)建了一個(gè)用戶:{{ name }}
{% endmacro %}

在index.html中引入function.html中定義的方法

{% from 'functions.html' import create_user %}

{{ create_user('小花') }}

2.3 循環(huán)

{% for item in cols %}

    aa

{% else %}

    bb

{% endfor %}

也可以獲取循環(huán)信息loop

loop.firstloop.lastloop.indexloop.revindex

例子:

在視圖中定義一個(gè)視圖函數(shù):

@stu.route('/scores/')def scores():

    scores_list = [21,34,32,67,89,43,22,13]

    content_h2 = '<h2>今天你們真帥</h2>'
    content_h3 = '   <h3>今天你們真帥</h3>   '

    return render_template('scores.html',
                           scores=scores_list,
                           content_h2=content_h2,
                           content_h3=content_h3)

(該視圖函數(shù),在下面講解的過(guò)濾器中任然使用其返回的content_h2等參數(shù))

首先: 在頁(yè)面中進(jìn)行解析scores的列表。題目要求:第一個(gè)成績(jī)展示為紅色,最后一個(gè)成績(jī)展示為綠色,其他的不變

<ul>
   {% for score in scores %}
        {% if loop.first %}            <li style="color:red;">{{ loop.revindex }}:{{ loop.index }}:{{ score }}</li>
        {% elif loop.last %}            <li style="color:green;">{{ loop.revindex }}:{{ loop.index }}:{{ score }}</li>
        {% else %}            <li> {{ loop.revindex }}:{{ loop.index }}:{{ score }}</li>
        {% endif %}
    {% endfor %}</ul>

2.4 過(guò)濾器

語(yǔ)法:

{{ 變量|過(guò)濾器|過(guò)濾器... }}

capitalize 單詞首字母大寫(xiě)

lower 單詞變?yōu)樾?xiě)

upper 單詞變?yōu)榇髮?xiě)

title

trim 去掉字符串的前后的空格

reverse 單詞反轉(zhuǎn)

format

striptags 渲染之前,將值中標(biāo)簽去掉

safe 講樣式渲染到頁(yè)面中

default

last 最后一個(gè)字母

first

length

sum

sort

例子:

<ul>
    <li>{{ content_h2 }}</li>
    <li>{{ content_h2|safe }}</li>
    <li>{{ content_h2|striptags }}</li>

    <li>{{ content_h3 }}</li>
    <li>{{ content_h3|length }}</li>
    <li>{{ content_h3|trim|safe }}</li>
    <li>{{ content_h3|trim|length }}</li></ul>

3. 定義模板

3.1 定義基礎(chǔ)模板base.html

<!DOCTYPE html><html lang="en"><head>
    <meta charset="UTF-8">
    <title>
        {% block title %}
        {% endblock %}    </title>
    <script src="https://code./jquery-3.2.1.min.js"></script>

    {% block extCSS %}
    {% endblock %}</head><body>{% block header %}
{% endblock %}

{% block content%}
{% endblock %}

{% block footer%}
{% endblock %}

{% block extJS %}
{% endblock %}</body></html>

3.2 定義基礎(chǔ)模板base_main.html

{% extends 'base.html' %}

{% block extCSS %}
    <link rel="stylesheet" href="{{ url_for('static', filename='css/main.css') }}">
{% endblock %}

4. 靜態(tài)文件信息配置

<b>django</b>:

第一種方式:

{% load static %}
<link rel="stylesheet" href="{% static 'css/index.css' %}">

第二種方式:

<link rel="stylesheet" href="/static/css/index.css">

<b>flask</b>:

第一種方式:

<link rel="stylesheet" href="/static/css/index.css">

第二種方式:

<link rel="stylesheet" href="{{ url_for('static', filename='css/index.css') }}">

flask使用操作指南之模型1


1. Flask模型

Flask默認(rèn)并沒(méi)有提供任何數(shù)據(jù)庫(kù)操作的API

我們可以選擇任何適合自己項(xiàng)目的數(shù)據(jù)庫(kù)來(lái)使用

Flask中可以自己的選擇數(shù)據(jù),用原生語(yǔ)句實(shí)現(xiàn)功能,也可以選擇ORM(SQLAlchemy,MongoEngine)

SQLAlchemy是一個(gè)很強(qiáng)大的關(guān)系型數(shù)據(jù)庫(kù)框架,支持多種數(shù)據(jù)庫(kù)后臺(tái)。SQLAlchemy提供了高層ORM,也提供了使用數(shù)據(jù)庫(kù)原生SQL的低層功能。

ORM:

將對(duì)對(duì)象的操作轉(zhuǎn)換為原生SQL
優(yōu)點(diǎn)
    易用性,可以有效減少重復(fù)SQL
    性能損耗少
    設(shè)計(jì)靈活,可以輕松實(shí)現(xiàn)復(fù)雜查詢
    移植性好

針對(duì)于Flask的支持,官網(wǎng)地址

pip install flask-sqlalchemy

安裝驅(qū)動(dòng)

pip install pymysql

2. 定義模型

使用SQLALchemy的對(duì)象去創(chuàng)建字段

其中tablename指定創(chuàng)建的數(shù)據(jù)庫(kù)的名稱

創(chuàng)建models.py文件,其中定義模型from flask_sqlalchemy import SQLAlchemy

db = SQLAlchemy()


class Student(db.Model):

    s_id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    s_name = db.Column(db.String(16), unique=True)
    s_age = db.Column(db.Integer, default=1)

    __tablename__ = "student"

其中:

Integer表示創(chuàng)建的s_id字段的類型為整形,

primary_key表示是否為主鍵

String表示該字段為字符串

unique表示該字段唯一

default表示默認(rèn)值

autoincrement表示是否自增

3. 創(chuàng)建數(shù)據(jù)表

在視圖函數(shù)中我們引入models.py中定義的db

from App.models import db@blue.route("/createdb/")def create_db():
    db.create_all()    return "創(chuàng)建成功"@blue.route('/dropdb/')def drop_db():
    db.drop_all()    return '刪除成功'

其中: db.create_all()表示創(chuàng)建定義模型中對(duì)應(yīng)到數(shù)據(jù)庫(kù)中的表

db.drop_all()表示刪除數(shù)據(jù)庫(kù)中的所有的表

4. 初始化SQLALchemy

在定義的init.py文件中使用SQLALchemy去整合一個(gè)或多個(gè)Flask的應(yīng)用

有兩種方式:

第一種:from flask_sqlalchemy import SQLALchemy

app = Flask(__name__)
db = SQLAlchemy(app)

第二種:from App.models import dbdef create_app():
    app = Flask(__name__)
    db.init_app(app)    return app

5. 配置數(shù)據(jù)庫(kù)的訪問(wèn)地址

官網(wǎng)配置參數(shù)

數(shù)據(jù)庫(kù)連接的格式:

dialect+driver://username:password@host:port/databasedialect數(shù)據(jù)庫(kù)實(shí)現(xiàn)

driver數(shù)據(jù)庫(kù)的驅(qū)動(dòng)

例子:
訪問(wèn)mysql數(shù)據(jù)庫(kù),驅(qū)動(dòng)為pymysql,用戶為root,密碼為123456,數(shù)據(jù)庫(kù)的地址為本地,端口為3306,數(shù)據(jù)庫(kù)名稱HelloFlask

設(shè)置如下: "mysql+pymysql://root:123456@localhost:3306/HelloFlask"

在初始化init.py文件中如下配置:

app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = Falseapp.config['SQLALCHEMY_DATABASE_URI'] = "mysql+pymysql://root:123456@localhost:3306/HelloFlask"

6. 對(duì)學(xué)生數(shù)據(jù)進(jìn)行CRUD操作

語(yǔ)法:

類名.query.xxx

獲取查詢集:

all()

filter(類名.屬性名==xxx)

filter_by(屬性名=xxx)

數(shù)據(jù)操作:

在事務(wù)中處理,數(shù)據(jù)插入db.session.add(object)db.session.add_all(list[object])db.session.delete(object)db.session.commit()

修改和刪除基于查詢

6.1 想學(xué)生表中添加數(shù)據(jù)

@blue.route('/createstu/')def create_stu():

    s = Student()
    s.s_name = '小花%d' % random.randrange(100)
    s.s_age = '%d' % random.randrange(30)

    db.session.add(s)
    db.session.commit()    return '添加成功'

提交事務(wù),使用commit提交我們的添加數(shù)據(jù)的操作

6.2 獲取所有學(xué)生信息

將學(xué)生的全部信息獲取到,并且返回給頁(yè)面,在頁(yè)面中使用for循環(huán)去解析即可

@blue.route("/getstudents/")def get_students():
    students = Student.query.all()    return render_template("StudentList.html", students=students)

6.3 獲取s_id=1的學(xué)生的信息

寫(xiě)法1:

students = Student.query.filter(Student.s_id==1)

寫(xiě)法2:

students = Student.query.filter_by(s_id=2)

注意:filter中可以接多個(gè)過(guò)濾條件

寫(xiě)法3:

sql = 'select * from student where s_id=1'students = db.session.execute(sql)

6.4 修改學(xué)生的信息

寫(xiě)法1:

students = Student.query.filter_by(s_id=3).first()
students.s_name = '哈哈'db.session.commit()

寫(xiě)法2:

Student.query.filter_by(s_id=3).update({'s_name':'娃哈哈'})
 
db.session.commit()

6.5 刪除一個(gè)學(xué)生的信息

寫(xiě)法1:

students = Student.query.filter_by(s_id=2).first()
db.session.delete(students)
db.session.commit()

寫(xiě)法2:

students = Student.query.filter_by(s_id=1).all()
db.session.delete(students[0])
db.session.commit()

注意:filter_by后的結(jié)果是一個(gè)list的結(jié)果集

<b>重點(diǎn)注意:在增刪改中如果不commit的話,數(shù)據(jù)庫(kù)中的數(shù)據(jù)并不會(huì)更新,只會(huì)修改本地緩存中的數(shù)據(jù),所以一定需要db.session.commit()</b>

flask使用操作指南之模型2


1. 深入數(shù)據(jù)庫(kù)增刪改查

定義模型,并定義初始化的函數(shù):

class Student(db.Model):

    s_id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    s_name = db.Column(db.String(16), unique=True)
    s_age = db.Column(db.Integer, default=1)

    __tablename__ = "student"

    def __init__(self, name, age):
        self.s_name = name
        self.s_age = age

1.1 增--批量增加

第一種方式:

@blue.route('/createstus/')def create_users():
    stus = []    for i in range(5):        # 實(shí)例化Student的對(duì)象
        s = Student()        # 對(duì)象的屬性賦值
        s.s_name = '張三%s' % random.randrange(10000)
        s.s_age = '%d' % random.randrange(100)
        stus.append(s)    # 添加需要?jiǎng)?chuàng)建的數(shù)據(jù)
    db.session.add_all(stus)    # 提交事務(wù)到數(shù)據(jù)庫(kù)
    db.session.commit()    return '創(chuàng)建成功'

注:在創(chuàng)建單條數(shù)據(jù)的時(shí)候使用db.session.add(),在創(chuàng)建多條數(shù)據(jù)的時(shí)候使用db.session.add_all()

第二種方式:

@blue.route('/createstus/')def create_users():
    stus = []    for i in range(5):        # 使用類的初始化去創(chuàng)建Student對(duì)象
        s = Student('張三%s' % random.randrange(10000),                    '%d' % random.randrange(100))
        stus.append(s)

    db.session.add_all(stus)
    db.session.commit()    return '創(chuàng)建成功'

1.2 查--使用運(yùn)算符

獲取查詢集

filter(類名.屬性名.運(yùn)算符(‘xxx’))

filter(類名.屬性 數(shù)學(xué)運(yùn)算符  值)

運(yùn)算符:

contains: 包含
startswith:以什么開(kāi)始
endswith:以什么結(jié)束in_:在范圍內(nèi)
like:模糊__gt__: 大于
__ge__:大于等于
__lt__:小于
__le__:小于等于

篩選:

offset()limit()

order_by()

get()

first()

paginate()

邏輯運(yùn)算:

and_
    filter(and_(條件),條件…)

或    or_
    filter(or_(條件),條件…)

非    not_
    filter(not_(條件),條件…)

例子1:

  1. 查詢學(xué)生的id為3,4,5,6,16的的學(xué)生信息,使用<b>in_邏輯運(yùn)算</b>

    @blue.route('/getstubyids/')    def get_stu_by_ids():

        students = Student.query.filter(Student.s_id.in_([3,4,5,6,16]))        return render_template('StudentList.html', students=students)
  1. 查詢學(xué)生的年齡小于18歲的學(xué)生的信息

     Student.query.filter(Student.s_age < 18)
  2. 查詢學(xué)生的年齡小于18歲的學(xué)生的信息,<b>__lt__小于</b>

     students = Student.query.filter(Student.s_age.__lt__(15))
  3. 查詢學(xué)生的年齡小于等于18歲的學(xué)生的信息,<b>__le__小于等于</b>

     students = Student.query.filter(Student.s_age.__le__(15))
  4. 查詢學(xué)生的姓名以什么開(kāi)始或者以什么結(jié)尾的學(xué)生的信息<b>startswith和endswith</b>

     students = Student.query.filter(Student.s_name.startswith('張'))
     students = Student.query.filter(Student.s_name.endswith('2'))
  5. 查詢id=4的學(xué)生的信息

     Student.query.get(4)
     獲取的結(jié)果是學(xué)生的對(duì)象
  6. 模糊搜索like

     %:代表一個(gè)或者多個(gè)
     _:代表一個(gè)
     
     Student.query.filter(Student.s_name.like('%張%')) 
    
  7. 分頁(yè),查詢第二頁(yè)的數(shù)據(jù)4條

     第一個(gè)參數(shù)是那一頁(yè),第二個(gè)參數(shù)是一頁(yè)的條數(shù),第三個(gè)參數(shù)是是否輸出錯(cuò)誤信息
     students = Student.query.paginate(2, 4, False).items

例子2:

跳過(guò)offset幾個(gè)信息,截取limit結(jié)果的幾個(gè)值

# 按照id降序排列stus = Student.query.order_by('-s_id')# 按照id升序排列stus = Student.query.order_by('s_id')
stus = Student.query.order_by(asc('s_id'))
stus = Student.query.order_by('s_id asc')# 按照id降序獲取三個(gè)stus = Student.query.order_by('-s_id').limit(3)
stus = Student.query.order_by('s_id desc').limit(3)

from sqlalchemy import desc
stus = Student.query.order_by(desc('s_id')).limit(3)# 獲取年齡最大的一個(gè)stus = Student.query.order_by('-s_age').first()# 跳過(guò)3個(gè)數(shù)據(jù),查詢5個(gè)信息stus = Student.query.order_by('-s_age').offset(3).limit(5)# 跳過(guò)3個(gè)數(shù)據(jù)stus = Student.query.order_by('-s_age').offset(3)# 獲取id等于24的學(xué)生stus = Student.query.filter(Student.s_id==24)
stus = Student.query.get(24)

例子3:

  1. 查詢

    from sqlalchemy import and_, or_, not_

    <b>查詢多個(gè)條件</b>

    stus = Student.query.filter(Student.s_age==18, Student.s_name=='雅典娜')

    <b>and_ 并且條件</b>

    stus = Student.query.filter(and_(Student.s_age==18, Student.s_name=='雅典娜'))

    <b>or_ 或者條件</b>

    stus = Student.query.filter(or_(Student.s_age==18, Student.s_name=='火神'))

    <b>not_ 非</b>

    stus = Student.query.filter(not_(Student.s_age==18), Student.s_name=='火神')

    查詢姓名不包含'可愛(ài)‘,并且年齡不等于12的學(xué)生

    stus = Student.query.filter(not_(Student.s_name.contains('可愛(ài)')),
    not_(Student.s_age == 12))

例子4:

<b>分頁(yè):</b>


image.png

后端數(shù)據(jù)處理:

# 方法一:手動(dòng)實(shí)現(xiàn)分頁(yè),使用offset和limitpage = int(request.args.get('page', 1))
stus = Student.query.offset((page-1)*5).limit(5)# 方法二: 使用切片[:]s_page = (page - 1)*5
e_page = page * 5
stus = Student.query.all()[s_page: e_page]# 方法三:使用paginate# 查詢第幾頁(yè)的數(shù)據(jù)  page = int(request.args.get('page', 1))# 每一頁(yè)的條數(shù)多少,默認(rèn)為10條per_page = int(request.args.get('per_page', 10))# 查詢當(dāng)前第幾個(gè)的多少條數(shù)據(jù)paginate = Student.query.order_by('-s_id').paginate(page, per_page, error_out=False)

stus = paginate.items

前端數(shù)據(jù)展示:

<h2>學(xué)生信息</h2>{% for stu in stus %}
    id:{{ stu.s_id }}
    姓名:{{ stu.s_name }}
    年齡:{{ stu.s_age }}    <br>{% endfor %}<br>總頁(yè)數(shù): {{ paginate.pages }}<br>一共{{ paginate.total }}條數(shù)據(jù)<br>當(dāng)前頁(yè)數(shù):{{ paginate.page }}<br>{% if paginate.has_prev %}    <a href="/stupage/?page={{ paginate.prev_num }}">上一頁(yè)</a>:{{ paginate.prev_num }}
{% endif %}

{% if paginate.has_next %}    <a href="/stupage/?page={{ paginate.next_num }}">下一頁(yè)</a>:{{ paginate.next_num }}
{% endif %}<br><br>頁(yè)碼:{% for i in  paginate.iter_pages() %}        <a href="/stupage/?page={{ i }}">{{ i }}</a>
    {% endfor %}

2. 關(guān)聯(lián)關(guān)系

2.1 一對(duì)多建立模型

學(xué)生模型:

class Student(db.Model):

    s_id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    s_name = db.Column(db.String(20), unique=True)
    s_age = db.Column(db.Integer, default=18)
    s_g = db.Column(db.Integer, db.ForeignKey('grade.g_id'), nullable=True)

    __tablename__ = 'student'

班級(jí)模型:

class Grade(db.Model):

    g_id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    g_name = db.Column(db.String(10), unique=True)
    g_desc = db.Column(db.String(100), nullable=True)
    g_time = db.Column(db.Date, default=datetime.now)
    students = db.relationship('Student', backref='stu', lazy=True)

    __tablename__ = 'grade'

官網(wǎng)解釋有如下幾個(gè)lazy的參數(shù):

lazy 決定了 SQLAlchemy 什么時(shí)候從數(shù)據(jù)庫(kù)中加載數(shù)據(jù):,有如下四個(gè)值:

<b>select</b>/True: (which is the default) means that SQLAlchemy will load the data as necessary in one go using a standard select statement.

<b>joined</b>/False: tells SQLAlchemy to load the relationship in the same query as the parent using a JOIN statement.

<b>subquery</b>: works like ‘joined’ but instead SQLAlchemy will use a subquery.

<b>dynamic</b>: is special and useful if you have many items. Instead of loading the items SQLAlchemy will return another query object which
you can further refine before loading the items. This is usually what you want if you expect more than a handful of items for this relationship

select就是訪問(wèn)到屬性的時(shí)候,就會(huì)全部加載該屬性的數(shù)據(jù)。

joined則是在對(duì)關(guān)聯(lián)的兩個(gè)表進(jìn)行join操作,從而獲取到所有相關(guān)的對(duì)象。

dynamic則不一樣,在訪問(wèn)屬性的時(shí)候,并沒(méi)有在內(nèi)存中加載數(shù)據(jù),而是返回一個(gè)query對(duì)象, 需要執(zhí)行相應(yīng)方法才可以獲取對(duì)象,

2.2

  1. 通過(guò)班級(jí)查詢學(xué)生信息

    @grade.route('/selectstubygrade/<int:id>/')    
    def select_stu_by_grade(id):
        grade = Grade.query.get(id)        # 通過(guò)班級(jí)對(duì)象.定義的relationship變量去獲取學(xué)生的信息
        stus = grade.students    
        return render_template('grade_student.html',
                               stus=stus,
                               grade=grade
                               )
  1. 通過(guò)學(xué)生信息查詢班級(jí)信息

    @stu.route('/selectgradebystu/<int:id>/')    def select_grade_by_stu(id):

        stu = Student.query.get(id)        # 通過(guò)學(xué)生對(duì)象.定義的backref參數(shù)去獲取班級(jí)的信息
        grade = stu.stu    
        return render_template('student_grade.html',
                               grade=grade,
                               stu=stu)

注意:表的外鍵由db.ForeignKey指定,傳入的參數(shù)是表的字段。db.relations它聲明的屬性不作為表字段,第一個(gè)參數(shù)是關(guān)聯(lián)類的名字,backref是一個(gè)反向身份的代理,相當(dāng)于在Student類中添加了stu的屬性。例如,有Grade實(shí)例dept和Student實(shí)例stu。dept.students.count()將會(huì)返回學(xué)院學(xué)生人數(shù);stu.stu.first()將會(huì)返回學(xué)生的學(xué)院信息的Grade類實(shí)例。一般來(lái)講db.relationship()會(huì)放在一這一邊。

3. 數(shù)據(jù)庫(kù)遷移

在django中繼承了makemigrations,可以通過(guò)migrate操作去更新數(shù)據(jù)庫(kù),修改我們定義的models,然后在將模型映射到數(shù)據(jù)庫(kù)中。

在flask中也有migrate操作,它能跟蹤模型的變化,并將變化映射到數(shù)據(jù)庫(kù)中

2.1 安裝migrate

pip install flask-migrate

2.2 配置使用migrate

2.2.1 初始化,使用app和db進(jìn)行migrate對(duì)象的初始化
from flask_migrate import Migrate#綁定app和數(shù)據(jù)庫(kù)Migrate(app=app, db=db)
2.2.2 安裝了flask-script的話,可以在Manager()對(duì)象上添加遷移指令
from flask_migrate import Migrate, MigrateCommand

app = Flask(__name__)

manage = Manager(app=app)

manage.add_command('db', MigrateCommand)

操作:

python manage.py db init  初始化出migrations的文件,只調(diào)用一次python manage.py db migrate  生成遷移文件python manage.py db upgrade 執(zhí)行遷移文件中的升級(jí)python manage.py db downgrade 執(zhí)行遷移文件中的降級(jí)python manage.py db --help 幫助文檔

flask使用操作指南之模型3


1. 關(guān)聯(lián)關(guān)系---多對(duì)多

定義模型:

引入SLALchemy

from flask_sqlalchemy import SQLAlchemy

db = SQLAlchemy()

創(chuàng)建中間表

sc = db.Table('sc',
    db.Column('s_id', db.Integer, db.ForeignKey('student.s_id'), primary_key=True),
    db.Column('c_id', db.Integer, db.ForeignKey('courses.c_id'), primary_key=True)
)

創(chuàng)建學(xué)生類Student

class Student(db.Model):

    s_id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    s_name = db.Column(db.String(20), unique=True)
    s_age = db.Column(db.Integer, default=18)
    s_g = db.Column(db.Integer, db.ForeignKey('grade.g_id'), nullable=True)

    __tablename__ = 'student'

    def __init__(self, name, age):

        self.s_name = name
        self.s_age = age
        self.s_g = None

創(chuàng)建課程表的模型,Course類

class Course(db.Model):

    c_id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    c_name = db.Column(db.String(20), unique=True)
    students = db.relationship('Student',
                               secondary=sc,
                               backref='cou')

    __tablename__ = 'courses'

    def __init__(self, name):

        self.c_name = name

sc表由<font style="color:red;">db.Table聲明</font>,我們不需要關(guān)心這張表,因?yàn)檫@張表將會(huì)由SQLAlchemy接管,它唯一的作用是作為students表和courses表關(guān)聯(lián)表,所以必須在db.relationship()中指出<font style="color:red;">sencondary關(guān)聯(lián)表參數(shù)</font>。lazy是指查詢時(shí)的惰性求值的方式,這里有詳細(xì)的參數(shù)說(shuō)明,而db.backref是聲明反向身份代理,其中的lazy參數(shù)是指明反向查詢的惰性求值方式.

2. 添加學(xué)生和課程之間的關(guān)系

通過(guò)頁(yè)面中傳遞學(xué)生的id和課程的id,分別獲取學(xué)生的對(duì)象和課程的對(duì)象,在使用關(guān)聯(lián)關(guān)系append去添加學(xué)生對(duì)象,并且add以后再commit后,就可以在中間表sc中查看到新增的關(guān)聯(lián)關(guān)系了。

    userid = request.form.get('userid')
    courseid = request.form.get('courseid')

    stu = Student.query.get(userid)
    cou = Course.query.get(courseid)

    cou.students.append(stu)
    db.session.add(cou)
    db.session.commit()

3. 刪除學(xué)生和課程之間的關(guān)系

通過(guò)頁(yè)面獲取傳遞的學(xué)生的id和課程的id,分別獲取學(xué)生對(duì)象和課程對(duì)象,在使用關(guān)聯(lián)關(guān)系remove去刪除學(xué)生對(duì)象,并commit將事務(wù)提交到數(shù)據(jù)庫(kù)中

stu = Student.query.get(s_id)
cou = Course.query.get(c_id)

cou.students.remove(stu)
db.session.commit()

4. 通過(guò)課程查詢學(xué)生的信息

以下定義在課程course的模型中,所以通過(guò)課程查詢學(xué)生的信息,<font style="color:red;">語(yǔ)法為課程的對(duì)象.studengs</font>。如果知道學(xué)生的信息反過(guò)來(lái)找課程的信息,則使用backref的反向關(guān)聯(lián)去查詢,<font style="color:red;">語(yǔ)語(yǔ)法為學(xué)生的對(duì)象.cou(反向)</font>

students = db.relationship('Student',secondary=sc,backref='cou')

cou = Course.query.get(2)
stus = cou.students

5. 通過(guò)學(xué)生去查詢課程的信息

stu = Student.query.get(id)
cous = stu.cou

flask使用操作指南之插件


1. 開(kāi)發(fā),頁(yè)面調(diào)試工具debugtoolbar

1.1 安裝

pip install flask-debugtoolbar

1.2 配置

from flask import Flaskfrom flask_debugtoolbar import DebugToolbarExtension

app = Flask(__name__)

app.debug = Trueapp.config['SECRET_KEY'] = '<replace with a secret key>'toolbar = DebugToolbarExtension(app)

2. restful

Flask-RESTful 提供的最主要的基礎(chǔ)就是資源(resources)。資源(Resources)是構(gòu)建在 Flask 可拔插視圖 之上,只要在你的資源(resource)上定義方法就能夠容易地訪問(wèn)多個(gè) HTTP 方法

官網(wǎng)上描述了一個(gè)最簡(jiǎn)單的restful風(fēng)格的api,如下:

from flask import Flaskfrom flask.ext import restful

app = Flask(__name__)
api = restful.Api(app)class HelloWorld(restful.Resource):
    def get(self):
        return {'hello': 'world'}

api.add_resource(HelloWorld, '/')if __name__ == '__main__':
    app.run(debug=True) 

2.1 安裝

pip install flask_restful

2.2 配置

在create_app()獲取Flask(name)對(duì)象中,設(shè)置如下配置

from flask_restful import Api

api = Api()

api.init_app(app=app)

在views中需要引入配置的api還有Resource

# 導(dǎo)入包和restful中的Api對(duì)象from flask_restful import Resourcefrom utils.functions import api# 定義類,啟動(dòng)包含了對(duì)數(shù)據(jù)處理的GET,POST,PATCH,PUT,DELETE請(qǐng)求class CreateCourse(Resource):def get(self, id):
    course = Course.query.get(id)    return course.to_dict()def post(self):

    courses = ['大學(xué)英語(yǔ)', '大學(xué)物理', '線性代數(shù)', '高數(shù)',               'VHDL', 'ARM', '馬克思主義', '農(nóng)場(chǎng)勞動(dòng)']
    course_list = []    for course in courses:
        c = Course()
        c.c_name = course
        course_list.append(c)
    db.session.add_all(course_list)
    db.session.commit()

    courses = Course.query.all()    return [course.to_dict() for course in courses]def patch(self, id):
    c_name = request.form.get('c_name')
    course = Course.query.get(id)
    course.c_name = c_name
    db.session.commit()    return {'code': 200, 'data': course.to_dict(), 'msg': '請(qǐng)求成功'}def delete(self, id):
    course = Course.query.get(id)
    db.session.delete(course)
    db.session.commit()    return {'code': 200, 'msg': '刪除成功'}# 綁定處理urlapi.add_resource(CreateCourse, '/api/course/<int:id>/', '/api/course/')

2.3 端點(diǎn)(Endpoints)

在一個(gè) API 中,你的資源可以通過(guò)多個(gè) URLs 訪問(wèn)。你可以把多個(gè) URLs 傳給 Api 對(duì)象的 Api.add_resource() 方法。每一個(gè) URL 都能訪問(wèn)到你的 Resource

如:

api.add_resource(CreateCourse, '/api/course/<int:id>/', '/api/course/')

2.4 返回響應(yīng)

Flask-RESTful 支持視圖方法多種類型的返回值。同 Flask 一樣,你可以返回任一迭代器,它將會(huì)被轉(zhuǎn)換成一個(gè)包含原始 Flask 響應(yīng)對(duì)象的響應(yīng)。Flask-RESTful 也支持使用多個(gè)返回值來(lái)設(shè)置響應(yīng)代碼和響應(yīng)頭

如:

def get(self, id):
    course = Course.query.get(id)    return course.to_dict(), 200

Django和Flask區(qū)別:


1. jiaji2和DjangoTemplates模板引擎相比,jiaja2語(yǔ)法更簡(jiǎn)單

比如: loop.indexforloop.counter
       loop.revindexforloop.revcounterjiaja2中沒(méi)有ifequal

2. 耦合

Django: 大而全,但是耦合性高。Auth,Permission,admin基本沒(méi)用
        開(kāi)發(fā)快,符合MVC模式

Flask: 微框架,很小巧。需要哪些功能,自己裝。
        需要熟悉MVC模式

3. 模型

3.1 模型定義

1. 模型中不定義數(shù)據(jù)庫(kù)的表名:
    在django中默認(rèn)表名為:'應(yīng)用app名_模型名小寫(xiě)'
    在flask中默認(rèn)的表名為:'模型名小寫(xiě)'2. 自增id字段:
    在django中默認(rèn)會(huì)創(chuàng)建自增的主鍵id
    在flask中需要自己寫(xiě)自增的主鍵id:
        id = db.Column(db.Integer, primary_key=True, autoincrement=True)3. 查詢所有數(shù)據(jù)的結(jié)果,all()方法
    在django中查詢的結(jié)果為QuerySet
    在Flask中查詢結(jié)果為List4. 查詢滿足條件的數(shù)據(jù)的結(jié)果,filter(), filter_by()方法
    在django中查詢的結(jié)果為QuerySet
    在Flask中查詢結(jié)果為BaseQuery objects

3.2 模型數(shù)據(jù)查詢

Django:

一對(duì)多:

  模型1: u 字段為 FOREIGN_KEY,關(guān)聯(lián)到模型2
    模型1.u = u對(duì)象
    模型1.u_id = u對(duì)象.id


  模型1查找模型2的數(shù)據(jù)
    模型2對(duì)象=模型1對(duì)象.u
    模型1對(duì)象=模型2對(duì)象.模型1_set.all()

一對(duì)一:

  模型1查找模型2的數(shù)據(jù)
    模型2對(duì)象=模型1對(duì)象.u
    模型1對(duì)象=模型2對(duì)象.模型1.all()

Flask:

一對(duì)多:

    模型1: u字段為FOREIGN KEY,關(guān)聯(lián)到模型2
    模型2: yy字段,定義relationship字段, backref=‘uu’

    模型1查找模型2:
        模型2對(duì)象 = 模型1對(duì)象.uu
        模型1對(duì)象 = 模型2對(duì)象.yy

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多