一:Python flask框架
前言
1.Python 物件導向的高階程式語言,以其語法簡單、免費開源、免編譯擴充套件性高,同時也可以嵌入到C/C++程式和豐富的第三方庫,Python運用到大資料分析、人工智慧、web後端等應用場景上。
2.Python 目前主要流行的web框架:flask、Django、Tornado
補充一下,我們前面學習的庫都是叫模組,那麼框架與庫的區別?
1.框架(framework)跟庫的功能類似,但是框架在某一領域上功能更加全面。使用框架,會減少開發者重複造輪子,直接呼叫其類或者函式就可以實現需求的功能。
2.那麼,我們本期來學習Python提供的 web 框架之一-flask框架相關方法的學習,Let's go~
二:flask 框架概述
1.簡介
1.falsk框架是一款基於WSGI的輕量級的Web框架,flask猶如耳詳的"麻雀雖小,五臟俱全",因此flask具有簡單可擴充套件性的特點.
2.Flask是一個基於Python開發並且依賴jinja2模板和Werkzeug WSGI服務的一個微型框架,對於Werkzeug本質是Socket服務端,其用於接收http請求並對請求進行預處理,然後觸發Flask框架,開發人員基於Flask框架提供的功能對請求進行相應的處理,並返回給使用者,如果要返回給使用者複雜的內容時,需要藉助jinja2模板來實現對模板的處理,即:將模板和資料進行渲染,將渲染後的字串返回給使用者瀏覽器。
3.“微”(micro) 並不表示你需要把整個 Web 應用塞進單個 Python 檔案(雖然確實可以 ),也不意味著 Flask 在功能上有所欠缺。微框架中的“微”意味著 Flask 旨在保持核心簡單而易於擴充套件。Flask 不會替你做出太多決策——比如使用何種資料庫。而那些 Flask 所選擇的——比如使用何種模板引擎——則很容易替換。除此之外的一切都由可由你掌握。如此,Flask 可以與您珠聯璧合。
2.須知:
1.預設情況下,Flask 不包含資料庫抽象層、表單驗證,或是其它任何已有多種庫可以勝任的功能。然而,Flask 支援用擴充套件來給應用新增這些功能,如同是 Flask 本身實現的一樣。眾多的擴充套件提供了資料庫整合、表單驗證、上傳處理、各種各樣的開放認證技術等功能。Flask 也許是“微小”的,但它已準備好在需求繁雜的生產環境中投入使用
3.flask框架的優勢
-
基於WSGI應用程式,必須使用顯式例項化
-
使用Werkzeug路由系統進行自動排序路由
-
使用Jinja2模板引擎,快速方便使用模板
-
使用執行緒區域性變數,實現快速訪問weby應用程式
-
支援非同步等待和ASCI(async-first)
-
銜接單元測試,開發人員快速進行測試檢查
-
自帶開發伺服器,無需藉助其他第三方網路服務
三:flask 安裝
1.安裝flask
pip3 install falsk
flask快速使用
2.flask執行流程(入門)
1.一旦請求過濾,執行app(),物件()---->觸發類的__call__()
2.請求一來,執行aap()---flask類的__call__方法執行
from flask import Flask
# 例項化產生一個Flask物件
app=Flask(__name__)
@app.route('/',methods=['GET',]) # 裝飾器(路由匹配)
def index(): # 檢視函式
return 'hello world lqz'
if __name__ == '__main__':
app.run(port=8080) # 最終呼叫了run_simple(),並傳埠,self
四:登入,顯示使用者資訊案例
1.案例:登入,顯示使用者資訊
1.template返回的html檔案必須放在template資料夾裡面(預設)
# 也可以自定製
app = Flask(__name__, render_template='a')
main.py
from flask import Flask,render_template,request,redirect,session,url_for
app = Flask(__name__)
app.debug = True
app.secret_key = 'sdfsdfsdfsdf'
USERS = {
1:{'name':'張三','age':18,'gender':'男','text':"道路千萬條"},
2:{'name':'李四','age':28,'gender':'男','text':"安全第一條"},
3:{'name':'王五','age':18,'gender':'女','text':"行車不規範"},
}
# 轉換器(int:nid)型別(引數get單查)
@app.route('/detail/<int:nid>',methods=['GET'])
def detail(nid):
user = session.get('user_info')
if not user:
return redirect('/login')
# 獲取USERS.get(使用者傳入id)
info = USERS.get(nid)
# 返回html頁面,USERS使用者資訊中的id(使用者選擇查詢)
return render_template('detail.html',info=info)
@app.route('/index',methods=['GET'])
def index():
user = session.get('user_info')
if not user:
# return redirect('/login') # 沒有登入重定向到login
url = url_for('l1') # 反向解析,django中severse
return redirect(url) # (沒登入,就重定向到login)
return render_template('index.html',user_dict=USERS) # 返回html頁面,USERS資訊
@app.route('/login',methods=['GET','POST'],endpoint='l1') # 路由中寫endpoint='li',那麼可以在檢視層中使用url_for反向解析出來,路由匹配的地址(login)
def login():
if request.method == "GET":
return render_template('login.html')
else:
# request.query_string
user = request.form.get('user') # django中使用request.POST--->flask: request.form
pwd = request.form.get('pwd')
if user == 'cxw' and pwd == '123':
session['user_info'] = user # 把登入資訊放到session中,加密後,以cookie形似,放到瀏覽器中
return redirect('http://www.baidu.com')
return render_template('login.html',error='使用者名稱或密碼錯誤')
if __name__ == '__main__':
app.run()
detail.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>詳細資訊 {{info.name}}</h1>
<div>
{{info.text}}
</div>
</body>
</html>
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>使用者列表</h1>
<table>
{% for k,v in user_dict.items() %}
<tr>
<td>{{k}}</td>
<td>{{v.name}}</td>
<td>{{v['name']}}</td>
<td>{{v.get('name')}}</td>
<td><a href="/detail/{{k}}">檢視詳細</a></td>
</tr>
{% endfor %}
</table>
</body>
</html>
login.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>使用者登入</h1>
<form method="post">
<input type="text" name="user">
<input type="text" name="pwd">
<input type="submit" value="登入">{{error}}
</form>
</body>
</html>
五:新手三件套
HttpResponse : '' 字串
render : render_template('模板.html', key=value錯誤或正確, key=value)
rediret : redirect
請求物件
request.GET : request.query_string
request.POST : request.form
路由寫法
urls.py : 裝飾器@app.route('地址', methods=[GET], endpoint='detail')
'地址' : 地址
methods : 請求方式
endpoint : 反向解析(路由解析,檢視反向解析)
轉換器
@app.route('/detail/<int:nid>',methods=['GET']) # 轉換器
def detail(nid): # 接收轉換器
反向解析
django中reverse : flask中url_for-->別名是endpoint指定的,如果不寫endpoint會有預設的,預設用函式名
# 裝飾器注意
1.如果檢視函式加多個裝飾器,一定要指定endpoint,不指定就會報錯
模板語法
跟dtl沒有區別,但是它更加強大,可以加括號,可以直接寫python語法
六:登入認證裝飾器
1.路由匹配成功才能執行登入認證裝飾器,所以登入裝飾器加在路由匹配下面
1.裝飾器(沒有登入,重定向到login)
def auth(func):
def inner(*args,**kwargs):
user = session.get('user_info')
if not user:
return redirect('/login') # 沒有登入,重定向到login
else:
res=func(*args,**kwargs)
return res
return inner
2.整體程式碼
from flask import Flask,request,render_template,redirect,session,url_for
# app = Flask(__name__,template_folder='a')
app = Flask(__name__)
app.debug = True # debug模式,開啟了,就會熱更新
app.secret_key = 'sdfsdfsdfsdf' # 祕鑰,django配置檔案中的祕鑰
def auth(func):
def inner(*args,**kwargs):
user = session.get('user_info')
if not user:
return redirect('/login') # 沒有登入,重定向到login
else:
res=func(*args,**kwargs)
return res
return inner
USERS = {
1:{'name':'張三','age':18,'gender':'男','text':"道路千萬條"},
2:{'name':'李四','age':28,'gender':'男','text':"安全第一條"},
3:{'name':'王五','age':18,'gender':'女','text':"行車不規範"},
}
@app.route('/login',methods=['GET','POST'])
def login():
if request.method == "GET":
return render_template('login.html') # 返回頁面
else:
# request.query_string
user = request.form.get('user') # django中使用request.POST--->flask:request.form
pwd = request.form.get('pwd')
if user == 'lqz' and pwd == '123':
session['user_info'] = user #把登入資訊放到session中,加密後,以cookie形式,放到瀏覽器中了
# return redirect('http://www.baidu.com') # 重定向到百度
return redirect(url_for('index')) # 重定向首頁
# return render_template('login.html',error='使用者名稱或密碼錯誤',name='lqz',age=19)
return render_template('login.html',error='使用者名稱或密碼錯誤')
@app.route('/index',methods=['GET'],endpoint='index')
@auth
def index():
# user = session.get('user_info')
# if not user:
# # return redirect('/login') # 沒有登入,重定向到login
# # 反向解析
# url = url_for('login') # django中叫 reverse
# return redirect(url)
return render_template('index.html',user_dict=USERS)
@app.route('/detail/<int:pk>',methods=['GET'],endpoint='detail')
@auth
def detail(pk):
user_detail=USERS[pk]
return render_template('detail.html',user_detail=user_detail)
if __name__ == '__main__':
app.run()
七:配置檔案
from flask import Flask,request,render_template,redirect,session,url_for
# 生成Flask物件
app = Flask(__name__)
1.配置資訊
# 方式一:直接通過app物件設定,只能設定這兩個,其他不支援
app.secret_key = 'sdfsdfsdfsdf' # 祕鑰,django配置檔案中的祕鑰
pp.debug = False # debug模式,開啟了,就會熱更新debug模式
# debug模式介紹:
1.flask預設是沒有開啟debug模式的,開啟debug模式有很多好處:第一,可以幫助我們查詢程式碼裡面的錯誤,比如:
# 方式二:直接通過app物件的config(字典)屬性設定
app.config['DEBUG']=True # debug模式
print(app.config)
# 方式三:直接使用py檔案(指定settings.py檔案內寫[配置資訊])
app.config.from_pyfile("settings.py")
通過環境變數配置
- 重點方式:後期用這種方式,使用類方式
# 寫法格式:
# app.config.from_object("python類或類的路徑")
# 可以直接指定配置檔案類路徑
# 優點:
1.開發上線測試直接寫多個類配置即可
2.方便切換,上線與未上線時的配置檔案配置
3.不需要像django一樣要重新建立一個配置檔案
# 使用
app.config.from_object('settings.DevelopmentConfig')
print(app.config['DATABASE_URI'])
if __name__ == '__main__':
app.run()
- 其他方式:(瞭解)
# app.config.from_envvar("環境變數名稱")
# app.config.from_json("json檔名稱")
# app.config.from_mapping({'DEBUG': True})
settings.py配置資料夾
class Config(object):
DEBUG = False
TESTING = False
DATABASE_URI = 'sqlite://:memory:'
class ProductionConfig(Config):
DATABASE_URI = 'mysql://user@localhost/foo'
class DevelopmentConfig(Config):
DEBUG = True
class TestingConfig(Config):
TESTING = True
內建配置引數(瞭解)
{
'DEBUG': get_debug_flag(default=False), 是否開啟Debug模式
'TESTING': False, 是否開啟測試模式
'PROPAGATE_EXCEPTIONS': None,
'PRESERVE_CONTEXT_ON_EXCEPTION': None,
'SECRET_KEY': None,
'PERMANENT_SESSION_LIFETIME': timedelta(days=31),
'USE_X_SENDFILE': False,
'LOGGER_NAME': None,
'LOGGER_HANDLER_POLICY': 'always',
'SERVER_NAME': None,
'APPLICATION_ROOT': None,
'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,
'MAX_CONTENT_LENGTH': None,
'SEND_FILE_MAX_AGE_DEFAULT': timedelta(hours=12),
'TRAP_BAD_REQUEST_ERRORS': False,
'TRAP_HTTP_EXCEPTIONS': False,
'EXPLAIN_TEMPLATE_LOADING': False,
'PREFERRED_URL_SCHEME': 'http',
'JSON_AS_ASCII': True,
'JSON_SORT_KEYS': True,
'JSONIFY_PRETTYPRINT_REGULAR': True,
'JSONIFY_MIMETYPE': 'application/json',
'TEMPLATES_AUTO_RELOAD': None,
}
八:路由系統
典型寫法
@app.route('/index/<name>',methods=['GET'],view_func='index',defaults={'name':'lqz'},strict_slashes=True,redirect_to='http://www.baidu.com')
# 引數:
methods : 允許的請求方式
defaults : 檢視函式名稱
strict_slashes : 嚴格模式
redirect_to : 訪問路由永久重定向
預設轉換器
DEFAULT_CONVERTERS = {
'default': UnicodeConverter,
'string': UnicodeConverter,
'any': AnyConverter,
'path': PathConverter,
'int': IntegerConverter,
'float': FloatConverter,
'uuid': UUIDConverter,
}
常用路由寫法
from flask import Flask,request,render_template,redirect,session,url_for
app = Flask(__name__)
app.debug = True # debug模式,開啟了,就會熱更新
app.secret_key = 'sdfsdfsdfsdf' # 祕鑰,django配置檔案中的祕鑰
@app.route('/index/<string:name>/<int:pk>',methods=['GET'],endpoint='index')
def index(name,pk):
print(name)
return 'hello'
if __name__ == '__main__':
app.run()
路由本質(解析)
1.當執行route路由時
2.路由本質解析原始碼
路由本質分析
def index(name,pk):
print(name)
return 'hello'
# 路由本質app.add_url_rule
app.add_url_rule('/index',endpoint='index',view_func=index,defaults={'name':'lqz','age':19})
if __name__ == '__main__':
app.run()
路由本質app.add_url_rule
1.路由系統的本質,就是 app.add_url_rule(路徑, 別名, 函式記憶體地址, **options)
2.endpoint:如果不填,預設就是函式名(加裝飾器時要注意)與django路由類似django與flask路由:flask路由基於裝飾器,本質是基於:add_url_rule
3.add_url_rule 原始碼中,endpoint如果為空,endpoint = _endpoint_from_view_func(view_func),最終取view_func.__name__(函式名)
add_url_rule的引數
# rule, URL規則
# view_func, 檢視函式名稱
# defaults = 預設為None, 預設值, 定義{'k':'v'}資料,那麼檢視函式也需要定義引數k接收當URL中無引數,函式需要引數時,使用defaults = {'k': 'v'} 為函式提供引數
# endpoint = None, 名稱,用於反向生成URL,即: url_for('名稱')
# methods = None, 允許的請求方式,如:["GET", "POST"]
strict_slashes = None(嚴格模式/非嚴格模式)
# 對URL最後的 / 符號是否嚴格要求
strict_slashes = None
# 設定True代表嚴格模式,訪問必須帶/,設定flase不需要帶/自定匹配
@app.route('/index', strict_slashes=False)
redirect_to永遠重定向該指定地址
# 重定向到指定地址
redirect_to = None, # 預設None
redirect_to = 'http://www.baidu.com' # 方法該路由永遠重定向該指定地址
@app.route('/index/<int:nid>', redirect_to='/home/<nid>')
九:CBV
1.我們研究flask中CBV原始碼發現與Django相同.
2.CBV原始碼:
1.執行as_view--返回dispatch,呼叫dispatch函式,通過反射,最終執行了/get或post請求.
2.flask中CBV原始碼與Django中相同
from flask import Flask,request,render_template,redirect,session,url_for
from flask.views import View,MethodView
app = Flask(__name__)
app.debug = True # debug模式,開啟了,就會熱更新
app.secret_key = 'sdfsdfsdfsdf' # 祕鑰,django配置檔案中的祕鑰
class IndexView(MethodView): # cbv必須要繼承MethodView
def get(self):
url=url_for('aaa') # 反向解析
print(url)
return '我是get'
def post(self):
return '我是post'
app.add_url_rule('/index',view_func=IndexView.as_view(name='aaa'))
if __name__ == '__main__':
app.run(port=8888)
總結cbv原始碼
1.endpoint:如果傳了,優先使用endpoint,如果不傳使用as_view(name='aaa'),但是name='aaa'必須傳
2.cbv要繼承MethodView,只需要寫get函式,post函式...
3.cbv要繼承View,必須重寫dispatch,與django中cbv相同
6 模版
flask中的模板語法:
# flask中的模板語法:
1.比django中多可以加括號,執行函式,傳引數
from flask import Flask,request,render_template,redirect,session,url_for,Markup
from flask.views import View,MethodView
app = Flask(__name__)
app.debug = True # debug模式,開啟了,就會熱更新
app.secret_key = 'sdfsdfsdfsdf' # 祕鑰,django配置檔案中的祕鑰
def test(a,b):
return a+b
class IndexView(MethodView): # 繼承MethodView
def get(self):
url=url_for('aaa') # 反向解析
print(url)
# html頁面顯示標籤
# a=Markup('<a href="http://www.baidu.com">點我看美女</a>')
a='<a href="http://www.baidu.com">點我看美女</a>'
return render_template('test.html',name='lqz',test=test,a=a)
def post(self):
return '我是post'
if __name__ == '__main__':
app.run(port=8888)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>{{name}}</h1>
<hr>
{{test(4,5)}} // 呼叫函式並傳參
<hr>
{{a}}
{{a|safe}} // 增加safe過濾器,顯示a標籤
</body>
</html>
html頁面(執行函式並傳參)
html頁面(顯示a標籤)
總結
1. 跟dtl完全一樣,但是它可以執行函式
2. Markup等價django的mark_safe ,
3.extends,include一模一樣