flask框架基礎

內容: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     }
flask默認配置

 

(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)經常使用路由

  • @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'])

經常使用路由系統有以上五種,全部的路由系統都是基於一下對應關係來處理:

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'))  
flask CBV

@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()
View Code

 

(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對應後面的參數
相關文章
相關標籤/搜索