內容:html
1.基礎的flask框架示例前端
2.flask配置文件python
3.flask路由系統mysql
4.請求和響應正則表達式
5.模板sql
flask框架預備知識:http://www.javashuo.com/article/p-qcqpurdg-dq.htmldjango
flask框架詳細學習:http://www.cnblogs.com/wupeiqi/articles/7552008.html json
1.基礎的flask框架示例flask
(1)基礎flask框架示例程序結構服務器
其中app.py是主程序,utils.py是功能函數模塊(log),templates文件夾中是HTML文件
(2)代碼
程序功能:訪問'/'顯示歡迎信息和連接,訪問'/message'顯示留言板,而後能夠用get提交數據,post提交數據,post提交的數據最後將顯示在頁面上
app.py:
1 from flask import ( 2 Flask, 3 render_template, 4 request, 5 redirect, 6 url_for, 7 ) 8 from utils import log 9 10 11 # 先要初始化一個 Flask 實例 12 app = Flask(__name__) 13 14 # message_list 用來存儲全部的 message 15 message_list = [] 16 17 18 # 定義路由和路由處理函數的方式以下 19 # ========================== 20 # 用 app.route 函數定義路由,參數是一個 path 路徑 21 # 下一行緊跟着的函數是處理這個請求的函數 22 # @ 是一個叫裝飾器的東西, 如今無必要知道具體的原理, 只要用它就行了 23 # 注意 methods 參數是一個 list,它規定了這個函數能接受的 HTTP 方法 默認是GET 24 @app.route('/', methods=['GET']) 25 def hello_world(): 26 return '<h1>Hello wyb666</h1><br><a href="/message">message</a>' 27 28 29 @app.route('/message') 30 def message_view(): 31 log('請求方法', request.method) 32 # render_template 讀取並返回 templates 文件夾中的模板文件 33 # messages 是傳給模板的參數,這樣就能在模板中使用這個變量 34 return render_template('message_index.html', messages=message_list) 35 36 37 # 這個路由函數只支持 POST 方法 38 @app.route('/message/add', methods=['POST']) 39 def message_add(): 40 log('message_add 請求方法', request.method) 41 42 # 把POST請求的數據生成一個 dict 存到 message_list 中去 43 msg = { 44 'content': request.form.get('msg_post', ''), 45 } 46 message_list.append(msg) 47 48 # 重定向: 49 return redirect('/message') 50 # 通常來講,咱們會用 url_for 生成路由 注意url_for的參數是路由函數的名字(格式爲字符串) 51 # return redirect(url_for('message_view')) 52 53 54 # 運行服務器 55 if __name__ == '__main__': 56 config = dict( 57 debug=True, # debug 模式能夠自動加載你對代碼的變更, 因此不用重啓程序 58 host='localhost', # 指定域名 59 port=80, # 指定端口 60 ) 61 app.run(**config)
utils.py:
1 # 一些工具函數 2 import time 3 4 5 # 用 log 函數把全部輸出寫入到屏幕中 方便debug 6 def log(*args, **kwargs): 7 formats = '%Y/%m/%d %H:%M:%S' 8 value = time.localtime(int(time.time())) 9 dt = time.strftime(formats, value) 10 print(dt, *args, **kwargs)
message_index.html:
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <!-- 指明字符編碼爲 utf-8 不然中文會亂碼 --> 5 <meta charset="utf-8"> 6 <title>留言板</title> 7 </head> 8 <body> 9 <h1>留言板</h1> 10 <form action="/message" method="GET"> 11 這是一個發送 GET 請求的表單 12 <br> 13 <textarea name="msg"></textarea> 14 <br> 15 <button type="submit">用 GET 提交表單</button> 16 </form> 17 18 <form action="/message/add" method="POST"> 19 這是一個發送 POST 請求的表單 20 <br> 21 <textarea name="msg_post"></textarea> 22 <br> 23 <button type="submit">用 POST 提交表單</button> 24 </form> 25 <!-- 下面是使用模板的辦法 --> 26 {# 這是 Jinja2 模板的註釋語法,這樣的註釋並不會在生成的 HTML 代碼中出現 #} 27 {# {% %} 裏面的是語句 #} 28 {# {{ }} 裏面的是引用變量 #} 29 <!-- 注意 m 自己是一個字典,可是你能夠用 . 的語法來引用 --> 30 <!-- 這是 Jinja2 模板的功能 --> 31 {% for m in messages %} 32 <div>{{ m.content }}</div> 33 {% endfor %} 34 </body> 35 </html>
2.flask配置文件
(1)flask默認配置以下:
1 flask中的配置文件是一個flask.config.Config對象(繼承字典),默認配置爲: 2 { 3 'DEBUG': get_debug_flag(default=False), # 是否開啓Debug模式 4 'TESTING': False, # 是否開啓測試模式 5 'PROPAGATE_EXCEPTIONS': None, 6 'PRESERVE_CONTEXT_ON_EXCEPTION': None, 7 'SECRET_KEY': None, 8 'PERMANENT_SESSION_LIFETIME': timedelta(days=31), 9 'USE_X_SENDFILE': False, 10 'LOGGER_NAME': None, 11 'LOGGER_HANDLER_POLICY': 'always', 12 'SERVER_NAME': None, 13 'APPLICATION_ROOT': None, 14 'SESSION_COOKIE_NAME': 'session', 15 'SESSION_COOKIE_DOMAIN': None, 16 'SESSION_COOKIE_PATH': None, 17 'SESSION_COOKIE_HTTPONLY': True, 18 'SESSION_COOKIE_SECURE': False, 19 'SESSION_REFRESH_EACH_REQUEST': True, 20 'MAX_CONTENT_LENGTH': None, 21 'SEND_FILE_MAX_AGE_DEFAULT': timedelta(hours=12), 22 'TRAP_BAD_REQUEST_ERRORS': False, 23 'TRAP_HTTP_EXCEPTIONS': False, 24 'EXPLAIN_TEMPLATE_LOADING': False, 25 'PREFERRED_URL_SCHEME': 'http', 26 'JSON_AS_ASCII': True, 27 'JSON_SORT_KEYS': True, 28 'JSONIFY_PRETTYPRINT_REGULAR': True, 29 'JSONIFY_MIMETYPE': 'application/json', 30 'TEMPLATES_AUTO_RELOAD': None, 31 }
(2)flask經常使用配置方法
1 方式一: 2 app.config['DEBUG'] = True 3 PS: 因爲Config對象本質上是字典,因此還可使用app.config.update(...) 4 5 6 方式二: 7 app.config.from_pyfile("python文件名稱") 8 eg: 9 settings.py: 10 DEBUG = True 11 12 app.py: 13 app.config.from_pyfile("settings.py") 14 15 16 方式三: 17 app.config.from_object("python類或類的路徑") 18 eg: 19 settings.py: 20 class Config(object): 21 DEBUG = False 22 TESTING = False 23 DATABASE_URI = 'sqlite://:memory:' 24 25 class ProductionConfig(Config): 26 DATABASE_URI = 'mysql://user@localhost/foo' 27 28 class DevelopmentConfig(Config): 29 DEBUG = True 30 31 class TestingConfig(Config): 32 TESTING = True 33 34 app.py: 35 app.config.from_object('pro_flask.settings.TestingConfig') 36 37 PS: 從sys.path中已經存在路徑開始寫 38 39 40 PS: settings.py文件默認路徑要放在程序root_path目錄,若是instance_relative_config爲True,則就是instance_path目錄
3.flask路由系統
(1)經常使用路由
經常使用路由系統有以上五種,全部的路由系統都是基於一下對應關係來處理:
1 DEFAULT_CONVERTERS = { 2 'default': UnicodeConverter, 3 'string': UnicodeConverter, 4 'any': AnyConverter, 5 'path': PathConverter, 6 'int': IntegerConverter, 7 'float': FloatConverter, 8 'uuid': UUIDConverter, 9 }
(2)flask路由系統本質(註冊路由原理)
flask的路由系統比較特殊,是基於裝飾器來實現,關於裝飾器:http://www.cnblogs.com/wyb666/p/8748102.html,可是flask路由系統的本質是經過add_url_rule方法來實現,詳情看下面:
一個基本的路由:
1 @app.route('/', methods=['GET'], endpoint="hello") 2 def hello_world(): 3 return '<h1>Hello wyb666</h1><br><a href="/message">message</a>'
第一行以@開頭明顯是一個裝飾器,源碼及其解釋以下:
1 def route(self, rule, **options): 2 # 這是一個被用來給view函數註冊路由的裝飾器 3 # rule是URL規則 4 # options是一系列參數 好比methods(請求方法)、endpoint(反向查詢URL)等 (endpoint不寫默認就是函數名) 5 def decorator(f): 6 endpoint = options.pop('endpoint', None) 7 # add_url_rule其實就是將路由規則和相應的處理函數對應起來 8 # 相似django中的urls.py中的 9 self.add_url_rule(rule, endpoint, f, **options) 10 return f 11 return decorator
上面那個基本路由的本質:
1 @app.route('/', methods=['GET'], endpoint="hello") 2 def hello_world(): 3 pass 4 上面這段代碼至關於: 5 1. decorator = app.route('/', methods=['GET'], endpoint="hello") 6 2. @decorator -> decorator(hello_world) 7 3. endpoint = options.pop('endpoint', None) 8 # 添加路由對應關係 9 self.add_url_rule(rule='/', endpoint="hello", f=hello_world, **options) 10 return f
因而這樣寫也能夠:
1 def hello_world(): 2 return '你好!' 3 4 app.add_url_rule('/', "hello", hello_world, methods=['GET'])
總結:
flask的路由系統比較特殊,是基於裝飾器來實現,但flask路由系統的本質是經過add_url_rule方法來實現,也就是說在本質上和django並沒有太大的區別,也能夠像django那樣使用路由,將上述代碼進一步完善能夠實現django中的FBV
固然也能夠實現django中的CBV:
1 from flask import views 2 # 裝飾器 3 def auth(func): 4 def inner(*args, **kwargs): 5 print('before') 6 result = func(*args, **kwargs) 7 print('after') 8 return result 9 return inner 10 11 class IndexView(views.MethodView): 12 methods = ['GET', 'POST'] 13 decorators = [auth, ] 14 15 def get(self): 16 return 'Index.GET' 17 18 def post(self): 19 return 'Index.POST' 20 21 # name其實就是endpoint 22 # as_view: 返回一個函數,將普通的view函數 -> 捆綁了路由的view函數 23 app.add_url_rule('/index', view_func=IndexView.as_view(name='index'))
@app.route和app.add_url_rule的參數以下:
1 @app.route和app.add_url_rule參數: 2 rule, URL規則 3 view_func, 視圖函數名稱 4 defaults=None, 默認值,當URL中無參數,函數須要參數時,使用defaults={'k':'v'}爲函數提供參數 5 endpoint=None, 名稱,用於反向生成URL,即: url_for('名稱') 6 methods=None, 容許的請求方式,如:["GET","POST"] 7 8 9 strict_slashes=None, 對URL最後的 / 符號是否嚴格要求, 10 如: 11 @app.route('/index',strict_slashes=False), 12 訪問 http://www.xx.com/index/ 或 http://www.xx.com/index都可 13 @app.route('/index',strict_slashes=True) 14 僅訪問 http://www.xx.com/index 15 16 redirect_to=None, 重定向到指定地址 17 如: 18 @app.route('/index/<int:nid>', redirect_to='/home/<nid>') 19 或 20 def func(adapter, nid): 21 return "/home/888" 22 @app.route('/index/<int:nid>', redirect_to=func) 23 24 subdomain=None, 子域名訪問 25 from flask import Flask, views, url_for 26 27 app = Flask(import_name=__name__) 28 app.config['SERVER_NAME'] = 'wupeiqi.com:5000' 29 30 31 @app.route("/", subdomain="admin") 32 def static_index(): 33 """Flask supports static subdomains 34 This is available at static.your-domain.tld""" 35 return "static.your-domain.tld" 36 37 38 @app.route("/dynamic", subdomain="<username>") 39 def username_index(username): 40 """Dynamic subdomains are also supported 41 Try going to user1.your-domain.tld/dynamic""" 42 return username + ".your-domain.tld" 43 44 45 if __name__ == '__main__': 46 app.run()
(3)自定義正則路由匹配
不多用到,用到再看看下面的吧:
1 from flask import Flask, views, url_for 2 from werkzeug.routing import BaseConverter 3 4 app = Flask(import_name=__name__) 5 6 # 這個類必定要寫,而且繼承BaseConverter 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()
(4)藍圖與子域名實現
藍圖用於爲應用提供目錄劃分和模塊化路由的功能,在flask中,藍圖能夠擁有本身的靜態資源路徑、模板路徑,從而實現結構劃分
子域名相似xxx.douban.com的形式,好比book.douban.com、movie.douban.com、music.douban.com、time.douban.com
關於這二者詳情看此:http://www.javashuo.com/article/p-emgarktr-dn.html
4.請求和響應
(1)flask請求
flask請求相關信息:
1 request.method -> 請求方法 2 request.args -> get請求參數 3 request.form -> post請求參數 4 request.values -> 全部請求參數 5 request.cookies -> 請求的cookies 6 request.headers -> 請求的headers 7 request.path -> 請求的路徑 8 request.full_path -> 請求的完整路徑 9 request.script_root 10 request.url 11 request.base_url 12 request.url_root 13 request.host_url 14 request.host 15 request.files -> 文件
關於flask上傳文件:
1 前端: 2 <form action="" enctype='multipart/form-data' method='POST'> 3 <input type="file" name="file"> 4 <input type="submit" value="上傳文件"> 5 </form> 6 flask: 7 file = request.files.get("file") # 獲取文件 8 filename = file.filename # 獲取文件名 9 file.save(os.path.join(FILE_DIR,filename)) # 保存文件
(2)flask響應
flask響應相關信息:
1 return "字符串" # 直接返回字符串 2 return render_template('html模板路徑') # 返回HTML 3 return render_template('html模板路徑', xxx=xxx) # 返回HTML並傳參(xxx=xxx也能夠寫成**{}的形式) 4 return redirect('/index.html') # 重定向 5 6 response = make_response(render_template('index.html')) # response是flask.wrappers.Response類型 7 response.delete_cookie('key') # 刪除cookie 8 response.set_cookie('key', 'value') # 設置cookie 9 response.headers['X-Something'] = 'A value' 10 return response
5.模板
(1)模板的使用
Flask使用的是Jinja2模板,其語法和Django無差異
(2)自定義模板方法
Flask中自定義模板方法的方式和Bottle類似,建立一個函數並經過參數的形式傳入render_template,而後將執行這個函數並將其最後結果替換到HTML中函數的位置,如:
1 <!DOCTYPE html> 2 <html> 3 <head lang="en"> 4 <meta charset="UTF-8"> 5 <title></title> 6 </head> 7 <body> 8 <h1>自定義函數</h1> 9 {{func()|safe}} 10 11 </body> 12 </html>
1 from flask import Flask,render_template 2 3 app = Flask(__name__) 4 5 def index(): 6 return '<h1>index</h1>' 7 8 @app.route('/test', methods=['GET', 'POST']) 9 def test(): 10 # index.html就是上面的HTML 11 return render_template('index.html', func=index) 12 13 app.run()
注意爲了防止XSS攻擊,直接傳HTML時會對HTML進行轉義,HTML將以字符串的形式直接顯示在頁面上,須要在模板上函數調用後加上| safe才能夠把HTML顯示出來
flask模板定製功能:
1 @app.template_global() 2 def sb(a1, a2): 3 return a1 + a2 4 # HTML中調用方法: 5 # {{ sb(1, 2)}} # 1和2分別對應兩個參數 6 7 @app.template_filter() 8 def db(a1, a2, a3): 9 return a1 + a2 + a3 10 # HTML中調用方法: 11 # {{ 1|db(2, 3)}} # 1對應第一個參數 2和3對應後面的參數