一、flask a、Flask是一個基於Python開發並且依賴jinja2模板和Werkzeug WSGI服務的一個微型框架,對於Werkzeug本質是Socket服務端,其用於接收http請求並對請求進行預處理,然後觸發Flask框架,開發人員基於Flask框架提供的功能對請求進行相應的處理,並 ...
一、flask
a、Flask是一個基於Python開發並且依賴jinja2模板和Werkzeug WSGI服務的一個微型框架,對於Werkzeug本質是Socket服務端,其用於接收http請求並對請求進行預處理,然後觸發Flask框架,開發人員基於Flask框架提供的功能對請求進行相應的處理,並返回給用戶,如果要返回給用戶複雜的內容時,需要藉助jinja2模板來實現對模板的處理,即:將模板和數據進行渲染,將渲染後的字元串返回給用戶瀏覽器
b、“微”(micro) 並不表示你需要把整個 Web 應用塞進單個 Python 文件(雖然確實可以 ),也不意味著 Flask 在功能上有所欠缺。微框架中的“微”意味著 Flask 旨在保持核心簡單而易於擴展。Flask 不會替你做出太多決策——比如使用何種資料庫。而那些 Flask 所選擇的——比如使用何種模板引擎——則很容易替換。除此之外的一切都由可由你掌握。如此,Flask 可以與您珠聯璧合。
c、預設情況下,Flask 不包含資料庫抽象層、表單驗證,或是其它任何已有多種庫可以勝任的功能。然而,Flask 支持用擴展來給應用添加這些功能,如同是 Flask 本身實現的一樣。眾多的擴展提供了資料庫集成、表單驗證、上傳處理、各種各樣的開放認證技術等功能。Flask 也許是“微小”的,但它已準備好在需求繁雜的生產環境中投入使用。
二、安裝
a、安裝:pip3 install flask
三、虛擬環境
a、安裝: pip3 install virtualenv
b、# 創建虛擬環境 virtualenv env1
c、# 進入虛擬環境 Scripts/activate
d、 # 退出虛擬環境 Scripts/deactivate
四、flask框架
a、簡介:輕量級框架
Django:無socket、中間件、路由系統、視圖(CBV,FBV)、 模板、ORM、cookie、Session、Admin、Form、緩存、信號、序列化....
Flask:無socket、中間件(擴展)、路由系統、視圖(CBV)、第三方模板(jinja2)、cookie、Session弱爆了
b、 什麼是wsgi?
Web服務網管介面,協議。
c、Flask依賴一個實現了WSGI協議的模塊:werkzeug
五、flask
a、 -依賴於wsgi模塊:wsgiref,werkzeug,wsgi
b、 -實例化Flask對象
-靜態文件首碼 /xxx
-靜態文件目錄
-模板路徑
c、 添加路由關係
-將 Rule(url和視圖函數)添加到Flask對象的url_map欄位中
-兩種添加路由的方式
d、request
-request.form
-request.args
六、基本使用
from flask import Flask # 實例化Flask對象 app = Flask(__name__) # 生成路由關係,並把關係保存到某個地方,app對象的 url_map欄位中 @app.route('/xxxx') # @decorator def index(): return "Index" # def index(): # return "Index" # app.add_url_rule('/xxx', "n1", index) if __name__ == '__main__': # 啟動程式,監聽用戶請求 # 一旦請求到來,執行 app.__call__方法 # 封裝用戶請求 # 進行路由匹配 app.run()
a、保存session的數據存到了瀏覽器上,
- 優點:減輕了服務端的壓力
- 缺點:不安全
b、路由系統:
- @app.route('/post/<path:path>')
- @app.route('/login', methods=['GET', 'POST'])
- @app.route('/user/<username>')
- @app.route('/post/<int:post_id>')
- @app.route('/post/<float:post_id>')
七、路由系統
a、 -可傳入參數
@app.route('/user/<username>')
@qpp.route('/post/<int:post_id>',methods=['GET','POST'],endpoint='fff')
b、反向生成URL:url_for
c、擴展Flask的路由系統,讓它支持正則:
from flask import Flask,url_for app = Flask(__name__) # 定義轉換的類 from werkzeug.routing import BaseConverter class RegexConverter(BaseConverter): """ 自定義URL匹配正則表達式 """ def __init__(self, map, regex): super(RegexConverter, self).__init__(map) self.regex = regex def to_python(self, value): """ 路由匹配時,匹配成功後傳遞給視圖函數中參數的值 :param value: :return: """ return int(value) def to_url(self, value): """ 使用url_for反向生成URL時,傳遞的參數經過該方法處理,返回的值用於生成URL中的參數 :param value: :return: """ val = super(RegexConverter, self).to_url(value) return val # 添加到converts中 app.url_map.converters['xxx'] = RegexConverter # 進行使用 @app.route('/index/<xxx("\d+"):nid>',endpoint='xx') def index(nid): url_for('xx',nid=123) return "Index" if __name__ == '__main__': app.run()
八、請求響應
from flask import Flask from flask import request from flask import render_template from flask import redirect from flask import make_response app = Flask(__name__) @app.route('/login.html', methods=['GET', "POST"]) def login(): # 請求相關信息 # request.method # request.args # request.form # request.values # request.cookies # request.headers # request.path # request.full_path # request.script_root # request.url # request.base_url # request.url_root # request.host_url # request.host # request.files # obj = request.files['the_file_name'] # obj.save('/var/www/uploads/' + secure_filename(f.filename)) # 響應相關信息 # return "字元串" # return render_template('html模板路徑',**{}) # return redirect('/index.html') # response = make_response(render_template('index.html')) # response是flask.wrappers.Response類型 # response.delete_cookie('key') # response.set_cookie('key', 'value') # response.headers['X-Something'] = 'A value' # return response return "內容" if __name__ == '__main__': app.run()
a、在django中用make_safe而在Flask中用make_response
九、模板語言
a、模板的使用
Flask使用的是Jinja2模板,所以其語法和Django無差別
b、自定義模板方法
Flask中自定義模板方法的方式和Bottle相似,創建一個函數並通過參數的形式傳入render_template,
十、session
a、 -session是否還有其他方法?
-它與字典方法相同
b、 -session超時時間如何設置:
app.config['SESSION_COOKIE_NAME'] = 'session_lvning' """ '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)
c、除請求對象之外,還有一個 session 對象。它允許你在不同請求間存儲特定用戶的信息。它是在 Cookies 的基礎上實現的,並且對 Cookies 進行密鑰簽名要使用會話,你需要設置一個密鑰。
d、
-
設置:session['username'] = 'xxx'
- 刪除:session.pop('username', None)
十一、閃現(flash)
a、session從在在服務端的一個字典中,session保存的數據取一次,它還是會有。而flash是基於session創建的,flash支持在裡面放值,只要在裡面取值它就會沒有。閃現就是
b、在session的基礎上,把它的值真實的放在session上,當去它的時候不僅把它的值取走,還把session的東西去掉。
十二、藍圖
a、藍圖用於為應用提供目錄劃分
- 藍圖URL首碼:xxx = Blueprint('account', __name__,url_prefix='/xxx')
- 藍圖子功能變數名稱:xxx = Blueprint('account', __name__,subdomain='admin')
# 前提需要給配置SERVER_NAME: app.config['SERVER_NAME'] = 'wupeiqi.com:5000'
# 訪問時:admin.wupeiqi.com:5000/login.html
十三、DBUtils
a、DBUtils是Python的一個用於實現資料庫連接池的模塊。
b、連接池的三種模式:
(1)、第一種模式:
它的缺點:每一次請求反覆創建資料庫的鏈接,鏈接的次數太多
(2)、第二種模式:
它的缺點:不能支持併發
(3)、第三種模式:
它是基於DBUtils實現資料庫連接池
-為每個線程創建一個鏈接,該線程關閉時,不是真正的關閉,本線程再次調用時,還是使用的最開始的創建的鏈接,知道線程終止,資料庫鏈接才關閉
-創建一個連接池(10個鏈接),為所有線程提供鏈接,使用時來進行獲取,使用完畢時,再次放回到連接池。
c、DBUtils的應用:
import time import pymysql import threading from DBUtils.PooledDB import PooledDB, SharedDBConnection POOL = PooledDB( creator=pymysql, # 使用鏈接資料庫的模塊 maxconnections=6, # 連接池允許的最大連接數,0和None表示不限制連接數 mincached=2, # 初始化時,鏈接池中至少創建的空閑的鏈接,0表示不創建 maxcached=5, # 鏈接池中最多閑置的鏈接,0和None不限制 maxshared=3, # 鏈接池中最多共用的鏈接數量,0和None表示全部共用。PS: 無用,因為pymysql和MySQLdb等模塊的 threadsafety都為1,所有值無論設置為多少,_maxcached永遠為0,所以永遠是所有鏈接都共用。 blocking=True, # 連接池中如果沒有可用連接後,是否阻塞等待。True,等待;False,不等待然後報錯 maxusage=None, # 一個鏈接最多被重覆使用的次數,None表示無限制 setsession=[], # 開始會話前執行的命令列表。如:["set datestyle to ...", "set time zone ..."] ping=0, # ping MySQL服務端,檢查是否服務可用。# 如:0 = None = never, 1 = default = whenever it is requested, 2 = when a cursor is created, 4 = when a query is executed, 7 = always host='127.0.0.1', port=3306, user='root', password='123', database='pooldb', charset='utf8' )
十四、session
a、 session和cookie的原理和區別:
cookie是保存在瀏覽器上的鍵值對
session是存在服務端的鍵值對(服務端的session就是一個大字典,字典中是隨機字元串)(session與request原理相同)(session原理跟上下文也有關係)
session依賴於cookie存在
b、 session流程
當請求第一次進來,生成隨機字元串 -發給用戶cookie -保存到session字典中時 它調用stark將隨機字元串和對應的值放到local 視圖函數 -使用時導入用top(它拿的是session) session=LocalProxy(partile(_lookup_req_object,'session ')) 請求處理完畢: 記憶體處理完畢後,將session做持久化(session存到資料庫,存到Redis,存到加密的cookie中)
十五、session源碼解析
a、先執行Flask的__call__方法 ,調用出來wsgi_app,它先做request的上下文做完,請求剛進來到push中,它先處理request將請求相關的數據,然後添加到了local中,
b、 緊接著處理session(將RequestContext對象(request,session)添加到local中),request(將request信息封裝到Request(environ)對象並複製給requestContext 對 象),然後獲取cookie中的隨機字元串,檢驗是否有,沒有就生成。根據隨機字元串,獲取服務端session保存的值。把session放到記憶體中,
c、 執行wsgi_app方法下麵的視圖函數。執行完視圖函數返回到full_dispatch_requesthong ,觸發只執行一次的裝飾器中(觸發Flask信號),
d、 執行完這個裝飾器,緊接著執行下麵的特殊的裝飾器,如果這些特殊裝飾器沒有返回值,那麼rv=None,如果有返回值,頁面時就顯示這個返回值,
e、如果沒有返回值,觸發執行那個視圖函數,拿返回值。請求執行完返回後,調用finalize_request,對它的返回值進行封裝。
十六、Flask和Django的區別
a、請求相關的數據
-Django:參數
-Flask: 基於Local,LocalStark對象
b、 多個請求進來會不會混淆
-單線程
-多線程
-協程
解決: from greenlet import getcurrent as get_ident
十七、Flask信號
a、 Flask框架中的信號基於blinker
b、安裝: pip3 install blinker
c、十個信號
1. 內置信號 10個信號: 2. request_started = _signals.signal('request-started') # 請求到來前執行 5. request_finished = _signals.signal('request-finished') # 請求結束後執行 3. before_render_template = _signals.signal('before-render-template') # 模板渲染前執行 4. template_rendered = _signals.signal('template-rendered') # 模板渲染後執行 2/3/4/5或不執行 got_request_exception = _signals.signal('got-request-exception') # 請求執行出現異常時執行 6. request_tearing_down = _signals.signal('request-tearing-down') # 請求執行完畢後自動執行(無論成功與否) 7. appcontext_tearing_down = _signals.signal('appcontext-tearing-down')# 請求上下文執行完畢後自動執行(無論成功與否) 1. appcontext_pushed = _signals.signal('appcontext-pushed') # 請求app上下文push時執行 8. appcontext_popped = _signals.signal('appcontext-popped') # 請求上下文pop時執行 message_flashed = _signals.signal('message-flashed') # 調用flask在其中添加數據時,自動觸發
d、flask信號本生自己沒有,用的是別人的,並且這些信號通過裝飾器全部可以代替了的,但是Django裡面有些特殊的
就是那些model操作根本沒有裝飾器,就是同過內置的信號來完成的
十八、django內置的信號
Request/response signals request_started # 請求到來前,自動觸發 request_finished # 請求結束後,自動觸發 got_request_exception # 請求異常後,自動觸發 Model signals pre_init # django的modal執行其構造方法前,自動觸發 post_init # django的modal執行其構造方法後,自動觸發 pre_save # django的modal對象保存前,自動觸發 post_save # django的modal對象保存後,自動觸發 pre_delete # django的modal對象刪除前,自動觸發 post_delete # django的modal對象刪除後,自動觸發 m2m_changed # django的modal中使用m2m欄位操作第三張表(add,remove,clear)前後,自動觸發 class_prepared # 程式啟動時,檢測已註冊的app中modal類,對於每一個類,自動觸發 Management signals pre_migrate # 執行migrate命令前,自動觸發 post_migrate # 執行migrate命令後,自動觸發 Test signals setting_changed # 使用test測試修改配置文件時,自動觸發 template_rendered # 使用test測試渲染模板時,自動觸發 Database Wrappers connection_created # 創建資料庫連接時,自動觸發
十九、Wtform
a、WTForms是一個支持多個web框架的form組件,主要用於對用戶請求數據進行驗證。
b、安裝: pip3 install wtform
c、用途:
1、用戶登錄註冊
當用戶登錄時候,需要對用戶提交的用戶名和密碼進行多種格式校驗。如:
用戶不能為空;用戶長度必須大於6;密碼不能為空;密碼長度必須大於12;密碼必須包含 字母、數字、特殊字元等(自定義正則);
#!/usr/bin/env python # -*- coding:utf-8 -*- from flask import Flask, render_template, request, redirect from wtforms import Form from wtforms.fields import core from wtforms.fields import html5 from wtforms.fields import simple from wtforms import validators from wtforms import widgets app = Flask(__name__, template_folder='templates') app.debug = True class LoginForm(Form): name = simple.StringField( label='用戶名', validators=[ validators.DataRequired(message='用戶名不能為空.'), validators.Length(min=6, max=18, message='用戶名長度必須大於%(min)d且小於%(max)d') ], widget=widgets.TextInput(), render_kw={'class': 'form-control'} ) pwd = simple.PasswordField( label='密碼', validators=[ validators.DataRequired(message='密碼不能為空.'), validators.Length(min=8, message='用戶名長度必須大於%(min)d'), validators.Regexp(regex="^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[$@$!%*?&])[A-Za-z\d$@$!%*?&]{8,}", message='密碼至少8個字元,至少1個大寫字母,1個小寫字母,1個數字和1個特殊字元') ], widget=widgets.PasswordInput(), render_kw={'class': 'form-control'} ) @app.route('/login', methods=['GET', 'POST']) def login(): if request.method == 'GET': form = LoginForm() return render_template('login.html', form=form) else: form = LoginForm(formdata=request.form) if form.validate(): print('用戶提交數據通過格式驗證,提交的值為:', form.data) else: print(form.errors) return render_template('login.html', form=form) if __name__ == '__main__': app.run()app.py
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1>登錄</h1> <form method="post"> <!--<input type="text" name="name">--> <p>{{form.name.label}} {{form.name}} {{form.name.errors[0] }}</p> <!--<input type="password" name="pwd">--> <p>{{form.pwd.label}} {{form.pwd}} {{form.pwd.errors[0] }}</p> <input type="submit" value="提交"> </form> </body> </html>login
二十、SQLALchemy
a、介紹 :
SQLALchemy是一個基於Python實現的ORM框架。該框架是建立在DB API之上,使用關係對象映射進行資料庫操作
簡言之便就是:將類和對象轉換成SQL,然後使用數據API執行SQL並獲取執行的結果
b、安裝: pip3 install SQLALchemy
c、組成部分
engine, 框架的引擎 Connection Pooling , 資料庫連接池 Dialect, 選擇鏈接資料庫的DB API種類 Schema /Types, 架構和類型 SQL Exprression Language, SQL表達式語言
d、SQLALcheam本省無法操作資料庫,其必須來pymysql等第三方插件, Dialect用於數據API的交流,根據配置文件的不同
調用不同的資料庫API,從而實現對資料庫的操作
MySQL-Python mysql+mysqldb://<user>:<password>@<host>[:<port>]/<dbname> pymysql mysql+pymysql://<username>:<password>@<host>/<dbname>[?<options>] MySQL-Connector mysql+mysqlconnector://<user>:<password>@<host>[:<port>]/<dbname> cx_Oracle oracle+cx_oracle://user:pass@host:port/dbname[?key=value&key=value...] 更多:http://docs.sqlalchemy.org/en/latest/dialects/index.html