Flask是一個使用 Python 編寫的輕量級 Web 應用框架。其 WSGI 工具箱採用 Werkzeug ,模板引擎則使用 Jinja2 。html
由於它使用簡單的核心,用 extension 增長其餘功能。Flask沒有默認使用的數據庫、窗體驗證工具。前端
1.實例化flask對象python
app = Flask(__name__,template_folder='templates',static_url_path='/static')
2.添加路由的方式正則表達式
方式一: @app.route('/login') def index(): return render_template('login.html') 方式二: def login(): return render_template('login.html') app.add_url_rule('/login', "n1", login) #'n1'爲別名
3.添加路由關係redis
將url和視圖函數封裝成一個Rule對象)添加到Flask的url_map字段中(詳見)數據庫
4.flask+自定義裝飾器(簡單登陸驗證)json
1 from flask import Flask,render_template,request,redirect,session 2 app = Flask(__name__,template_folder='templates',static_url_path='/static') 3 app.secret_key = "asdfafsd" #加鹽做用,必須有值 4 5 @app.route('/login',methods=['GET','POST']) 6 def login(): 7 if request.method == 'GET': 8 return render_template('login.html') 9 else: 10 user = request.form.get('user') 11 pwd = request.form.get('pwd') 12 if user == '張良' and pwd == '123': 13 session['user_info'] = user 14 return redirect('/index') 15 else: 16 return render_template('login.html',msg='用戶名或者密碼錯誤!') 17 18 def deco(func): 19 def _deco(*args,**kwargs): 20 if not session.get('user_info'): 21 return redirect('/login') 22 return func(*args, **kwargs) 23 return _deco 24 25 @app.route('/index',methods=['GET']) 26 @deco #調用裝飾器函數寫在路由下面 27 def index(): 28 return render_template('index.html') 29 30 if __name__ == '__main__': 31 app.run() 32 33 login.html 34 <body> 35 <form method="post"> 36 <p>用戶名<input type="text" name="user"></p> 37 <p>密 碼<input type="text" name="pwd"></p> 38 <input type="submit">{{ msg }} 39 </form> 40 </body>
5.請求響應相關flask
1 request.form #POST請求,獲取表單內容 2 request.args #GET請求,字典形式的,獲取url中傳過來的鍵值對 3 request.querystring #GET請求,bytes形式的 4 request.url #返回當前請求完整的URL 5 request.base_url #不帶參數的URL 6 request.path #url中的路徑部分
from urllib.parse import urlencode,quote,unquote,make_response get_data = request.args #ImmutableMultiDict([''id':'1','name':'tom']) get_dict = get_data.to_dict #{''id':'1','name':'tom'} get_dict['xx] = 18 url = urlencode(get_dict) #id=1&name=tom&xx=18 request.files obj = request.files['the_file_name'] obj.save('/var/www/uploads/' + secure_filename(f.filename)) #請求文件中的url中若是有中文,會獲得: val = "%E6%8A%8A%E5%87%A0%E4%B8%AA" 解碼: unquote(val) #返回更多的內容 response = make_response("xxxx") response.header['xxx'] = ‘123’ return response
5.路由系統後端
@app.route('/user/<username>') @app.route('/post/<int:post_id>') @app.route('/post/<float:post_id>') @app.route('/post/<path:path>') @app.route('/login', methods=['GET', 'POST']) 經常使用路由系統有以上五種,全部的路由系統都是基於一下對應關係來處理: DEFAULT_CONVERTERS = { 'default': UnicodeConverter, 'string': UnicodeConverter, 'any': AnyConverter, 'path': PathConverter, 'int': IntegerConverter, 'float': FloatConverter, 'uuid': UUIDConverter, }
@app.route和app.add_url_rule參數:
1 rule, URL規則 2 view_func, 視圖函數名稱 3 defaults=None, 默認值,當URL中無參數,函數須要參數時,使用defaults={'k':'v'}爲函數提供參數 4 endpoint=None, 名稱,用於反向生成URL,即: url_for('名稱') 5 methods=None, 容許的請求方式,如:["GET","POST"] 6 7 8 strict_slashes=None, 對URL最後的 / 符號是否嚴格要求, 9 如: 10 @app.route('/index',strict_slashes=False), 11 訪問 http://www.xx.com/index/ 或 http://www.xx.com/index都可 12 @app.route('/index',strict_slashes=True) 13 僅訪問 http://www.xx.com/index 14 redirect_to=None, 重定向到指定地址 15 如: 16 @app.route('/index/<int:nid>', redirect_to='/home/<nid>') 17 或 18 def func(adapter, nid): 19 return "/home/888" 20 @app.route('/index/<int:nid>', redirect_to=func) 21 subdomain=None, 子域名訪問 22 from flask import Flask, views, url_for 23 24 app = Flask(import_name=__name__) 25 app.config['SERVER_NAME'] = 'wupeiqi.com:5000' 26 27 28 @app.route("/", subdomain="admin") 29 def static_index(): 30 """Flask supports static subdomains 31 This is available at static.your-domain.tld""" 32 return "static.your-domain.tld" 33 34 35 @app.route("/dynamic", subdomain="<username>") 36 def username_index(username): 37 """Dynamic subdomains are also supported 38 Try going to user1.your-domain.tld/dynamic""" 39 return username + ".your-domain.tld" 40 41 42 if __name__ == '__main__': 43 app.run()
URL反向解析cookie
from flask import Flask, url_for def index(): v = url_for("xxx") print(v) return "index" @app.route('/zzz/<int:nid>',endpoint="aaa") #endpoint是別名 def zzz(nid): v = url_for("aaa",nid=nid) print(v) return "index2"
redirect_to:直接重定向,原url有參數時,跳轉時也要傳參,注意:不用加類型
6.自定製正則路由匹配
1 from flask import Flask, views, url_for 2 from werkzeug.routing import BaseConverter 3 4 app = Flask(import_name=__name__) 5 6 7 class RegexConverter(BaseConverter): 8 """ 9 自定義URL匹配正則表達式 10 """ 11 def __init__(self, map, regex): 12 super(RegexConverter, self).__init__(map) 13 self.regex = regex 14 15 def to_python(self, value): 16 """ 17 路由匹配時,匹配成功後傳遞給視圖函數中參數的值 18 :param value: 19 :return: 20 """ 21 return int(value) 22 23 def to_url(self, value): 24 """ 25 使用url_for反向生成URL時,傳遞的參數通過該方法處理,返回的值用於生成URL中的參數 26 :param value: 27 :return: 28 """ 29 val = super(RegexConverter, self).to_url(value) 30 return val 31 32 # 添加到flask中 33 app.url_map.converters['regex'] = RegexConverter 34 35 36 @app.route('/index/<regex("\d+"):nid>') 37 def index(nid): 38 print(url_for('index', nid='888')) 39 return 'Index' 40 41 42 if __name__ == '__main__': 43 app.run() 44 45 #自定製正則路由匹配
7.模板使用
和Django使用相似......
不一樣之處:
前端循環字典時,dict.items(),後面的括號須要加;後端傳來一個字典,前端可用get.('xxx')取值
markup:至關於Django的mark_safe;
template_global() template_filter() (在全部的頁面均可以使用)
1 @app.template_global() 2 def dd(a1, a2): 3 return a1 + a2 4 @app.template_filter() 5 def pp(a1, a2, a3): 6 return a1 + a2 + a3 7 8 調用:{{dd(1,2)}} {{ 1|pp(2,3)}}(用‘|’區分)
宏:只有定義的東西在不少地方去使用的時候纔去用它
1 {% macro input(name, type='text', value=' ') %} 2 <input type="{{ type }}" name="{{ name }}" value="{{ value }}"> 3 {% endmacro %} 4 5 {{ input('n1') }}
8.session
設置:session['username'] = 'xxx'
1 from flask import Flask, session, redirect, url_for, escape, request 2 3 app = Flask(__name__) 4 5 @app.route('/') 6 def index(): 7 if 'username' in session: 8 return 'Logged in as %s' % escape(session['username']) 9 return 'You are not logged in' 10 11 @app.route('/login', methods=['GET', 'POST']) 12 def login(): 13 if request.method == 'POST': 14 session['username'] = request.form['username'] 15 return redirect(url_for('index')) 16 return ''' 17 <form action="" method="post"> 18 <p><input type=text name=username> 19 <p><input type=submit value=Login> 20 </form> 21 ''' 22 23 @app.route('/logout') 24 def logout(): 25 # remove the username from the session if it's there 26 session.pop('username', None) 27 return redirect(url_for('index')) 28 29 # set the secret key. keep this really secret: 30 app.secret_key = 'A0Zr98j/3yX R~XHH!jmN]LWX/,?RT' 31 32 基本使用
pip3 install Flask-Session run.py from flask import Flask from flask import session from pro_flask.utils.session import MySessionInterface app = Flask(__name__) app.secret_key = 'A0Zr98j/3yX R~XHH!jmN]LWX/,?RT' app.session_interface = MySessionInterface() @app.route('/login.html', methods=['GET', "POST"]) def login(): print(session) session['user1'] = 'alex' session['user2'] = 'alex' del session['user2'] return "內容" if __name__ == '__main__': app.run() session.py #!/usr/bin/env python # -*- coding:utf-8 -*- import uuid import json from flask.sessions import SessionInterface from flask.sessions import SessionMixin from itsdangerous import Signer, BadSignature, want_bytes class MySession(dict, SessionMixin): def __init__(self, initial=None, sid=None): self.sid = sid self.initial = initial super(MySession, self).__init__(initial or ()) def __setitem__(self, key, value): super(MySession, self).__setitem__(key, value) def __getitem__(self, item): return super(MySession, self).__getitem__(item) def __delitem__(self, key): super(MySession, self).__delitem__(key) class MySessionInterface(SessionInterface): session_class = MySession container = {} def __init__(self): import redis self.redis = redis.Redis() def _generate_sid(self): return str(uuid.uuid4()) def _get_signer(self, app): if not app.secret_key: return None return Signer(app.secret_key, salt='flask-session', key_derivation='hmac') def open_session(self, app, request): """ 程序剛啓動時執行,須要返回一個session對象 """ sid = request.cookies.get(app.session_cookie_name) if not sid: sid = self._generate_sid() return self.session_class(sid=sid) signer = self._get_signer(app) try: sid_as_bytes = signer.unsign(sid) sid = sid_as_bytes.decode() except BadSignature: sid = self._generate_sid() return self.session_class(sid=sid) # session保存在redis中 # val = self.redis.get(sid) # session保存在內存中 val = self.container.get(sid) if val is not None: try: data = json.loads(val) return self.session_class(data, sid=sid) except: return self.session_class(sid=sid) return self.session_class(sid=sid) def save_session(self, app, session, response): """ 程序結束前執行,能夠保存session中全部的值 如: 保存到resit 寫入到用戶cookie """ domain = self.get_cookie_domain(app) path = self.get_cookie_path(app) httponly = self.get_cookie_httponly(app) secure = self.get_cookie_secure(app) expires = self.get_expiration_time(app, session) val = json.dumps(dict(session)) # session保存在redis中 # self.redis.setex(name=session.sid, value=val, time=app.permanent_session_lifetime) # session保存在內存中 self.container.setdefault(session.sid, val) session_id = self._get_signer(app).sign(want_bytes(session.sid)) response.set_cookie(app.session_cookie_name, session_id, expires=expires, httponly=httponly, domain=domain, path=path, secure=secure) 自定義Session
#!/usr/bin/env python # -*- coding:utf-8 -*- """ pip3 install redis pip3 install flask-session """ from flask import Flask, session, redirect from flask.ext.session import Session app = Flask(__name__) app.debug = True app.secret_key = 'asdfasdfasd' app.config['SESSION_TYPE'] = 'redis' from redis import Redis app.config['SESSION_REDIS'] = Redis(host='192.168.0.94',port='6379') Session(app) @app.route('/login') def login(): session['username'] = 'alex' return redirect('/index') @app.route('/index') def index(): name = session['username'] return name if __name__ == '__main__': app.run() 第三方session
session配置參數
- session超時時間如何設置? app.config['SESSION_COOKIE_NAME'] = 'session_lvning' 跟session相關的配置文件 """ '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(days=31)
9.閃現
本質:flash是基於session建立的,flash支持往裏邊放值,只要你取一下就沒有了,至關於pop了一下。
1 from flask import Flask, flash, redirect, render_template, request, get_flashed_messages 2 app = Flask(__name__) 3 app.secret_key = 'some_secret' 4 flag = True 5 @app.route('/index') 6 def index1(): 7 global flag 8 if flag: 9 flash('登陸成功!') 10 flag=False 11 return render_template('index.html') 12 13 if __name__ == "__main__": 14 app.run(port=8600) 15 16 #index.html 17 <!DOCTYPE html> 18 <html lang="en"> 19 <head> 20 <meta charset="UTF-8"> 21 <title>Title</title> 22 </head> 23 <body> 24 {% for msg in get_flashed_messages() %} 25 <p>{{ msg }}</p> 26 {% endfor %} 27 </body> 28 </html>
10.flask中經過內置函數實現中間價的效果
from flask import Flask,session,Session,flash,get_flashed_messages,redirect,render_template,request
app = Flask(__name__)
app.secret_key ='sdfsdfsdf'
@app.before_request
def process_request1():
print('process_request1')
@app.after_request
def process_response1(response):
print('process_response1')
return response
@app.before_request
def process_request2():
print('process_request2')
@app.after_request
def process_response2(response): #參數也得有
print('process_response2')
return response #必須有返回值
#注:@app.before_first_request:當程序運行起來,第一個請求來的時候就只執行一次,下次再來就不會在執行了
11.flask中的CBV模式和FBV模式
1 def auth(func): 2 def inner(*args, **kwargs): 3 result = func(*args, **kwargs) 4 return result 5 return inner 6 7 class IndexView(views.MethodView): 8 # methods = ['POST'] #只容許POST請求訪問 9 decorators = [auth,] #若是想給全部的get,post請求加裝飾器,就能夠這樣來寫 10 11 def get(self): #若是是get請求須要執行的代碼 12 v = url_for('index') 13 print(v) 14 return "GET" 15 16 def post(self): #若是是post請求執行的代碼 17 return "POST" 18 19 app.add_url_rule('/index', view_func=IndexView.as_view(name='index')) #name指定的是別名,會當作endpoint使用 20 21 if __name__ == '__main__': 22 app.run()
1 方式一: 2 @app.route('/index',endpoint='xx') 3 def index(nid): 4 url_for('xx',nid=123) 5 return "Index" 6 7 方式二: 8 def index(nid): 9 url_for('xx',nid=123) 10 return "Index" 11 12 app.add_url_rule('/index',index)