flask 之(四) --- 擴展|緩存|會話

擴展 

藍圖內置擴展 (實現的是路由的拆分)
html

 1 '''----------- app.py -------------'''
 2 from flask import Flask  3 from users_views import blue1  4 from orders_views import blue2  5 
 6 app = Flask(__name__)  7 
 8 # 路由註冊
 9 app.register_blueprint(blueprint=blue1) 10 app.register_blueprint(blueprint=blue2) 11 
12 
13 if __name__ == '__main__': 14     app.run()
 1 ''' ------------ users_views.py ---------------'''
 2 from flask import Blueprint  3 # blue1 的設置(名字,導入的名字,前綴名稱)
 4 blue1 = Blueprint("blue1",__name__, url_prefix="/users")  5 
 6 # 用blue1設置路由,用前綴名字區分相同名字的路由:http://127.0.0.1:5000/users/
 7 @blue1.route("/")  8 def index():  9     return "用戶的 Blue 信息"
10 
11 
12 @blue1.route("/user/") 13 def home(): 14     return "用戶信息"
 1 ''' ----------- orders_vieews.py ----------'''
 2 from flask import Blueprint  3 # blue2 的設置(名字,導入的名字,前綴名稱)
 4 blue2 = Blueprint("blue2", __name__, url_prefix="/orders")  5 
 6 # 用blue2設置路由,用前綴名字區分相同名字的路由:http://127.0.0.1:5000/orders/
 7 @blue2.route("/")  8 def haha():  9     return "訂單的 blue2 信息"
10 
11 
12 @blue2.route("/orders/") 13 def ppp(): 14     return "訂單信息"

靜態文件路徑前端

1 from flask import Flask 2 from users_views import blue1 3 from orders_views import blue2 4 # 靜態文件路徑配置。static_folder='news/static' 是配置新的靜態文件的路徑
5 app = Flask(__name__,static_folder='news/static') 6 
7 # 路由註冊
8 app.register_blueprint(blueprint=blue1) 9 app.register_blueprint(blueprint=blue2)

終端命令啓動項目插件擴展:python

  • 實現:flask-script
  • 安裝:pip install flask-script
  • 做用:實現命令鍵入的方式 啓動項目
  • 使用:在終端鍵入:python app.py runserver 
    • 查看幫助文檔:  python app.py runserver --help
    • 設置指定端口:  python app.py runserver -h ip地址 -p 端口號
    • 設置自動重啓:  python app.py runserver -r
    • 設置調試模式:  python app.py runserver -d
    • shell腳本調試:  python app.py shell   在終端內添加model數據
  • 配置:
 1 from flask import Flask  2 from flask_script import Manager  3 
 4 app = Flask(__name__)  5 # 配置flask-script
 6 manager = Manager(app=app)  7 
 8 @app.route('/')  9 def hello_world(): 10     return 'Hello World!'
11 
12 # 使用flask-script
13 if __name__ == '__main__': 14  manager.run() 15 
16 flask-script

對象模型遷移數據庫表擴展:mysql

  • 實現:flask-migrate
  • 安裝:pip install flask-migrate -i http://pypi.douban.com/simple
  • 做用:遷移,能夠自動將模型轉變成數據庫中的表
  • 配置:
    • 在extension.py擴展文件中綁定app和db。詳見下面代碼塊 ;建立一個Migrate對象,傳遞app和db進去
    • 而後,在manage.py啓動文件的manager對象上添加指令:manager.add_command("db",MigrateCommand)
  • 使用:
    • 首次使用須要初始化:           python manage.py db init
    • 若是模型有變動,生成遷移文件:python manage.py db migrate
    • 將遷移文件映射到數據庫中:  python manage.py db upgrade
    • 後悔返回,回滾操做:     python manage.py db downgrade
  • extension.py
 1 from flask_migrate import Migrate  2 from flask_sqlalchemy import SQLAlchemy  3 
 4 db = SQLAlchemy()  5 # 擴展文件添加配置信息。建立一個Migrate對象。
 6 migate  = Migrate()  7 
 8 
 9 # 應用一個函數,使用函數傳參數將app導入初始化
10 def init_ext(app): 11  db.init_app(app) 12     migate.init_app(app,db) # 將app和db以參數的形式傳遞進去。註冊上
  •  manage.py
1 # 註冊遷移工具命令行
2 manager.add_command("db",MigrateCommand) 3 
4 if __name__ == '__main__': 5     manager.run()
  •  未拆分寫法
 1 from flask_migrate import Migrate, MigrateCommand  2 from flask_script import Manager  3 from app import create_app, db  4 
 5 app = create_app()  6 manager = Manager(app=app)  7 
 8 # 建立遷移工具實例
 9 migrate = Migrate() 10 migrate.init_app(app=app,db=db) 11 
12 
13 # 註冊遷移工具命令行
14 manager.add_command("db",MigrateCommand) 15 
16 if __name__ == '__main__': 17     manager.run()

數據庫模型和對象關係擴展web

  • 實現:SQLAlchemy;                 pymysql驅動
  • 安裝:pip install flask-sqlalchemy ;pip install pymysql
  • 做用:ORM(Object Relational Mapping) 對象關係映射。將數據庫轉爲面向對象的操做,經過操做對象就可實現對數據的CRUD
  • 配置:
 1 from flask import Flask, render_template  2 from flask_sqlalchemy import SQLAlchemy  3 
 4 app = Flask(__name__)  5 
 6 # 配置鏈接sqlite數據庫的指定信息。SQLite數據庫鏈接不須要額外驅動,也不須要用戶名和密碼
 7 app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///hello.sqlite'  
 8 # 設False爲更好的兼容性,禁止對象追蹤修改
 9 app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False  
11 db = SQLAlchemy(app) 12 
13 
14 # 配置鏈接mysql數據庫的指定信息。dialect+driver://username:password@host:port/database
15 app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+pymysql://root:guoyapeng@localhost:3306/FlaskModel'
16 app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False 
17 db = SQLAlchemy(app) 18 19 20 if __name__ == '__main__': 21 app.run()
  • 使用:下面連接文件中的 模型板塊

https://www.cnblogs.com/TMMM/p/11450872.htmlredis


緩存技術cache擴展庫插件:
sql

  • 實現:flask_caching
  • 安裝:pip install flask-caching
  • 做用:
    • 減小磁盤IO能夠大幅度提高服務器性能。
    • 數據庫IO操做的是web應⽤性能的瓶頸。爲了提⾼訪問效率,應儘量減小數據庫的操做。
    • 能夠將常常訪問的數據緩存起來,再次使⽤用時直接從緩存中獲取,而不是每次都操做數據庫。
  • 字段
from flask_caching import Cache cache = Cache() cache.init_app(app=app, config={'CACHE_TYPE': 'simple'})
 1 CACHE_REDIS_URL    # 鏈接到Redis服務器的URL。一鍵配置示例 
 2 cache = Cache(config={  3   "CACHE_TYPE": "redis",  4   "CACHE_REDIS_URL":"redis://:localhost@127.0.0.1:6379/1",})  5 
 6 # 如下參數是全部的類型共有的
 7 CACHE_NO_NULL_WARNING = "warning"  # null類型時的警告消息
 8 CACHE_ARGS = []              # 在緩存類實例化過程當中解包和傳遞的可選列表,用來配置相關後端的額外的參數
 9 CACHE_OPTIONS = {}           # 可選字典,在緩存類實例化期間傳遞,也是用來配置相關後端的額外的鍵值對參數
10 CACHE_DEFAULT_TIMEOUT        # 默認過時/超時時間,單位爲秒
11 CACHE_THRESHOLD              # 緩存的最大條目數
12 
13 CACHE_TYPE:                # 設置緩存的類型
14 CACHE_TYPE = null          # 默認的緩存類型,無緩存
15 CACHE_TYPE = 'simple'      # 使用本地python字典進行存儲,非線程安全
16 CACHE_TYPE = 'filesystem'  # 使用文件系統來存儲緩存的值
17 CACHE_TYPE = 'memcached'   # 使用memcached服務器緩存
18 CACHE_TYPE = 'redis'       # 使用redis做爲緩存
 1 CACHE_TYPE = 'filesystem' # 使用文件系統來存儲緩存的值
 2 CACHE_DIR = ""            # 文件目錄
 3 
 4 CACHE_TYPE = 'memcached'  # 使用memcached服務器緩存
 5 CACHE_KEY_PREFIX          # 設置cache_key的前綴
 6 CAHCE_MEMCACHED_SERVERS   # 服務器地址的列表或元組
 7 CACHE_MEMCACHED_USERNAME  # 用戶名
 8 CACHE_MEMCACHED_PASSWORD  # 密碼
 9 
10 CACHE_TYPE = 'redis'      # 使用redis做爲緩存
11 CACHE_KEY_PREFIX          # 設置cache_key的前綴
12 CACHE_REDIS_HOST          # redis地址
13 CACHE_REDIS_PORT          # redis端口
14 CACHE_REDIS_PASSWORD      # redis密碼
15 CACHE_REDIS_DB            # 使用哪一個數據庫
  • 配置
  • manage.py
from flask_script import Manager from app import create_app app = create_app() manager = Manager(app=app) if __name__ == '__main__': manager.run()
  • app/__init__.py
from flask import Flask from app import views, ext def create_app(): app = Flask(__name__)
# 註冊緩存配置 ext.init_cache(app) # 註冊路由 app.register_blueprint(views.bp) return app
  • app/ext.py
 1 from flask_caching import Cache  2 
 3 cache = Cache()  4 
 5 def init_cache(app):  6     
 7     # CACHE_TYPE = 'redis' 使用redis做爲緩存
 8     # CACHE_KEY_PREFIX 設置cache_key的前綴。不設置表示默認
 9     # CACHE_REDIS_HOST redis地址
10     # CACHE_REDIS_PORT redis端口
11     # CACHE_REDIS_PASSWORD redis密碼。沒密碼就不用設置
12     # CACHE_REDIS_DB 使用哪一個數據庫,不設置表示隨機
13     
14     app.config["CACHE_TYPE"] = "redis"
15     app.config["CACHE_REDIS_HOST"] = "127.0.0.1"
16     app.config["CACHE_REDIS_PORT"] = 6379
17     # 設置緩存到app上
18     cache.init_app(app=app)
  • 使用
  • movies/views.py
 1 from time import sleep  2 from app.ext import cache  3 
 4 @user_blue.route("/learn/")  5 @cache.cached(60) # 設置緩存,60秒有效
 6 def learn():  7     print("開始學習")  8     sleep(10)  9     print("結束學習") 10     return "緩存技術,提升學習時間"

會話技術session擴展庫插件shell

  • 實現:flask_session
  • 做用:實現http的長連接,用會話技術爲了數據能夠跨請求使用,讓服務器識別客戶端
  • 安裝:pip install flask-session
  • 配置:
 1 import datetime  2 from flask import Flask  3 from flask_session import Session  4 from app import views  5 
 6 def create_app():  7     
 8     app = Flask(__name__)  9 
10     # 爲sesson設置一個密鑰key值。兩種方式,推薦第二種
11     # app.secret_key = 'asdfghjkl'
12     app.config['SECRET_KEY'] = 'd53a40dae292df9d409ef64e4a04905d'
13 
14     # flssk-session 擴展配置
15     # 指定 flask-session 擴展將 session 數據持久化到 redis 中
16     app.config['SESSION_TYPE'] = 'redis'
17 
18     # 指定 flask-session 存儲在 redis 中的 session id的前綴
19     app.config['SESSION_KEY_PREFIX'] = 'flask:session'
20 
21     # 自定義 session 過時時間
22     app.config['PERMANENT_SESSION_LIFETIME'] = datetime.timedelta(days=7) 23 
24     # 建立 flask-session 的 Session 對象
25     sess = Session() 26 
27     # 將 flask-session 擴展初始化,跟app創建連接
28     sess.init_app(app=app) 29 
30     app.register_blueprint(views.bp)  # 註冊路由
31     return app
  • 使用: 如下連接中的 session會話 模塊

 https://www.cnblogs.com/TMMM/p/11478808.html數據庫


管理⽤戶登陸登出擴展庫插件:json

  • 實現:flask-login
  • 安裝:pip install flask-login
  • 做用:是一個專門用來管理用戶登陸退出的擴展庫
  • 步驟:
    • 1.  在extension.py中 app上註冊flask-login擴展,指定登錄頁面。以下兩行代碼
    • 2. 在model.py中 在登錄對象(User)中繼承 UserMixin類,提供便捷的功能
    • 3. 在views.py中 增長load_user回調函數,導入擴展文件包加裝飾器@login_manager.user_loader。
    •     供flask-login擴展在內部加載當前登錄的用戶對象。flask-login默認經過user id的方式,調用load_user函數,得到用戶對象
    • 4. 登錄成功後,調用login_user(user)將登錄成功的對象綁定到session中
    • 5. 使用lagin_required裝飾器,保護訪問受限的視圖函數
  • 配置:
    • manage.py 註冊
 1 # 添加擴展
 3 from flask import Flask  4 from flask.ext.login import LoginManager 
 6 app = Flask(__name__)  
 8 # 1.實例化login_manager
 9 login_manager = LoginManager()
10 # 2.將login_manager與app綁定 11 login_manager.init_app(app)
12 # 3.設置登陸視圖名稱。若是未登陸用戶請求只有登陸用戶才能訪問的視圖,則重定向到這個設置的登陸視圖。 13 login_manager.login_view = 'blue.login'

14 # 4.若是未設置登陸視圖,則直接返回401錯誤。設置登陸錯誤信息 15 login_manager.login_message = '請登陸!'
    • models.py 繼承
 1 from flask_login import UserMixin  2 from flask_sqlalchemy import SQLAlchemy  3 
 4 db = SQLAlchemy()  5 # 讓User繼承自UserMixin。
 6 class User(UserMixin,db.Model):  7     __tablename__= "users"
 8     id = db.Column(db.Integer,primary_key=True)  9     username = db.Column(db.String(16),unique=True,nullable=False) 10     password = db.Column(db.String(256),unique=True,nullable=False)
    • views.py 初始化
1 # 告訴ext.py中login_manager的用戶是從哪來的。用戶加載的地方
2 @login_manager.user_loader 3 def load_user(user_id): 4     return User.query.get(user_id)
  • 使用
 1 """
 2 狀態切換:  3   login_user # 登陸  4   logout_user # 退出登陸  5 
 6 路由保護:  7   login_required # 保護須要登陸才能訪問的路路由  8  
 9 當前用戶: 10   current_user # 哪⾥均可以使⽤(在模板中不須要分配) 11 
12 實現回調: 13   @login_manager.user_loader 14   def load_user(uid): 15    return User.query.get(uid) 16 """
 1 #屬性 is_authenticated
 2 #當用戶登陸成功後,該屬性爲True。
 3 
 4 #屬性 is_active
 5 #若是該用戶帳號已被激活,且該用戶已登陸成功,則此屬性爲True。
 6 
 7 #屬性 is_anonymous
 8 #是否爲匿名用戶(未登陸用戶)。
 9 
10 #方法 get_id()
11 #每一個用戶都必須有一個惟一的標識符做爲ID,該方法能夠返回當前用戶的ID,這裏ID必須是Unicode。
 7 <body>
 8 
 9 {# 當前用戶:current_user,屬性:is_authenticated 當前用戶登陸成功後該屬性爲True。 #} 10 {# 判斷用戶是否登錄,若是登錄顯示:用戶名、註銷、用戶主頁、關於網站。若是沒有登錄顯示:請登陸、用戶主頁、關於網站 #}
11 {% if current_user.is_authenticated %} 12 當前登錄用戶爲:{{ current_user.username }}<a href="{{ url_for("blue.logout") }}">註銷</a> 13 {% else %} 14 <a href="{{ url_for("blue.login") }}">請登陸</a> 15 {% endif %} 16 <a href="{{ url_for("blue.home") }}">用戶主頁</a> 17 <a href="{{ url_for("blue.about") }}">關於網站</a> 18 19 </body>
    • models.py
 1 from flask_login import UserMixin  2 from flask_sqlalchemy import SQLAlchemy  3 
 4 db = SQLAlchemy()  5 
 6 class User(UserMixin,db.Model):  7     __tablename__= "users"
 8     id = db.Column(db.Integer,primary_key=True)  9     username = db.Column(db.String(16),unique=True,nullable=False) 10     password = db.Column(db.String(256),unique=True,nullable=False)
    • views.py
 1 from flask import Blueprint, render_template, request, redirect, url_for, flash  2 from flask_login import login_user, logout_user, login_required  3 from werkzeug.security import generate_password_hash, check_password_hash  4 from app.ext import login_manager  5 from app.models import User, db  6 
 7 bp = Blueprint('blue', __name__)  8 
 9 
10 @bp.route('/register/', methods=['GET', 'POST']) 11 def register(): 12     if request.method == 'POST': 13         # 處理註冊邏輯。 一、檢查兩次輸入的密碼是否相等; 二、檢查用戶名是否重複
14         username = request.form.get('username') 15         password = request.form.get('password') 16         re_password = request.form.get('re_password') 17 
18         # 檢查兩次輸入的密碼是否相等
19         if password != re_password: 20             return render_template('register.html', msg='兩次輸入密碼不一致', username=username) 21         # 查詢數據庫中是否有重複的用戶名。 .count() 得到查詢語句匹配到的行數
22         if User.query.filter_by(username=username).count() > 0: 23             return render_template('register.html', msg='用戶名重複', username=username) 24 
25         # 對 password 進行加密。進行存儲準備
26         password_hash = generate_password_hash(password) 27         user = User() 28         user.username = username 29         user.password = password_hash 30         # 對新註冊的用戶進行存儲
31  db.session.add(user) 32  db.session.commit() 33 
34         # flash 閃現消息,能夠跨請求傳遞消息,不跨請求時也可使用
35         # 本質上:內部會把消息保存到 session中,在下一個請求中經過session獲取
36         """
37  在 html 中使用 38  {% for message in get_flashed_messages() %} 39  {{ message }} 40  {% endfor %} 41         """
42         flash('註冊成功,請登陸') 43         return redirect(url_for('blue.login')) 44     return render_template('register.html') 45 
46 @bp.route("/login/",methods=["POST","GET"]) 47 def login(): 48     if request.method == "POST": 49         # 處理登錄業務
50         username = request.form.get("username") 51         password = request.form.get("password") 52 
53         user = User.query.filter_by(username=username).first() 54         if user is None: 55             return render_template("login.html",msg="用戶或密碼錯誤",username=username) 56         if check_password_hash(user.password,password): 57 
58             # 登錄成功之後須要將登錄狀態保存到session中session['uid']=user.id,使用flask-login的login_user()來完成
59  login_user(user) 60 
61             # 即便是post請求,也能夠用args獲取跳轉連接next的參數值,http://127.0.0.1:5000/login/?next=%2Fhome%2F
62             next_url = request.args.get("next") 63             # 若是存在 next 跳轉參數,則跳轉到 next 頁面;不然調轉到首頁
64             return redirect(next_url or url_for("blue.index")) 65         else: 66             return render_template("login.html", msg="用戶或密碼錯誤", username=username) 67     return render_template("login.html") 68 
69 # 保護頁面。須要配置默認調轉頁面
70 # 使用裝飾器:@login_required 實現:只有登錄的用戶,點擊home時頁面纔會看到信息;沒有登錄的用戶點擊會被跳轉到登錄頁面
71 @bp.route("/home/") 72 @login_required 73 def home(): 74     return "home"
75 
76 # 登出操做。用 flask-login的logout_user()自動完成登出時session的清理工做
77 @bp.route("/logout/") 78 def logout(): 79  logout_user() 80     return redirect(url_for("blue.index")) 81 
82 # 告訴ext.py中login_manager的用戶是從哪來的。用戶加載的地方
83 @login_manager.user_loader 84 def load_user(user_id): 85     return User.query.get(user_id) 86 
87 
88 @bp.route("/about/") 89 def about(): 90     return "about"
91 
92 @bp.route('/') 93 def index(): 94     return render_template('index.html')
views.py

 表單驗證模塊擴展庫插件:

  • 實現:flask-wtf
  • 做用:是flask框架的表單驗證模塊。能夠很方便生成表單驗證表單的數據。CSRF、字段校驗等功能。
  • 安裝:pip install flask-wtf
  • 注意:若是使用form提交的話,自動將form.py中的屬性和html中的同名元素匹配,html中須要註明 {{ form.csrf_token }}
    • form.py中的 username = StringField(...)匹配 .html中的  <input name="username">

  • 字段

     

  SelectField:下拉框內容在 form 表單類初始化時即肯定。運行中修改不生效(驗證時會出錯)

  QuerySelectField:下拉框內容能夠動態從數據庫中獲取,query_factory指定查詢接口

  • 配置:
    • form.py
 1 from flask_wtf import FlaskForm  2 from wtforms import StringField, PasswordField  3 from wtforms.validators import DataRequired, Length, EqualTo  4 
 5 
 6 class RegisterForm(FlaskForm):  7     # 定義頁面中顯示的字段標籤。username是StringField類型
 8     username = StringField(  9         # label標籤 顯示:"用戶名"
10         label='用戶名', 11         # 驗證器:列表類型。
12         validators=[ 13             # DataRequired 必填信息
14             DataRequired(message='用戶名爲必填') 15  ] 16  ) 17     password = PasswordField( 18         label='密碼', 19         validators=[ 20             DataRequired(message='密碼爲必填'), 21             # 長度驗證(最小2,最長4)
22             Length(min=2, max=4, message='密碼長度爲 2 ~ 4'), 23  ] 24  ) 25     password_confirm = PasswordField( 26         label='重複密碼', 27         validators=[ 28             # EqualTo驗證和誰相等(要比較的變量)
29             EqualTo('password', message='兩次輸入的密碼必須一致'), 30  ] 31  ) 32 
33 
34 class LoginForm(FlaskForm): 35     username = StringField( 36         label='用戶名', 37         # 默認值:空
38         default='', 39         validators=[ 40             DataRequired(message='用戶名爲必填') 41  ] 42  ) 43     password = PasswordField( 44         label='密碼', 45         validators=[ 46             DataRequired(message='密碼爲必填'), 47  ] 48     )
  • 使用:
    • views.py
 1 from flask import Blueprint, render_template, request, redirect, url_for  2 from flask_login import login_user  3 from werkzeug.security import generate_password_hash, check_password_hash  4 from app.ext import login_manager  5 from app.form import RegisterForm, LoginForm  6 from app.models import User, db  7 
 8 bp = Blueprint('blue', __name__)  9 
10 
11 @bp.route('/form/register/', methods=['GET', 'POST']) 12 def register_form(): 13     form = RegisterForm() 14     # 普通寫法:
15     # if request.method == 'POST':
16     # username = request.form.get('username')
17 
18     # form寫法
19     # validate_on_submit 內部作了三件事
20     # 一、判斷 request.method 是否爲 POST, PUT, PATCH, DELETE
21     # 至關於 if request.method == 'POST'
22     # 二、將表單中的同名元素自動綁定到form中的同名屬性中
23     # 至關於 username = request.form.get('username')
24     # form.username = username
25     # 三、驗證表單數據,根據表單字段中定一個的 validators
26     if form.validate_on_submit(): 27         # 前端數據在form驗證經過後,從form獲取前端傳入的數據
28         print(form.data) 29         username = form.username.data 30         password = form.password.data 31 
32         password_hash = generate_password_hash(password) 33 
34         user = User() 35         user.username = username 36         user.password = password_hash 37 
38  db.session.add(user) 39  db.session.commit() 40         return redirect(url_for('blue.login_form')) 41     return render_template('register_form.html', form=form)  # 返回form對象數據
42 
43 
44 @bp.route('/form/login/', methods=['POST', 'GET']) 45 def login_form(): 46     form = LoginForm() 47 
48     # validate_on_submit 內部作了三件事
49     # 一、判斷 request.method是否爲POST, PUT, PATCH, DELETE
50     # 至關於 if request.method=='POST'
51     # 二、將表單中的同名元素自動綁定到form中的同名屬性中
52     # 至關於 username = request.form.get('username')
53     # form.username = username
54     # 三、驗證表單數據,根據表單字段中定一個的 validators
55     if form.validate_on_submit(): 56         username = form.username.data 57         password = form.password.data 58 
59         # 先根據用戶名查詢數據庫中是否有該數據
60         user = User.query.filter_by(username=username).first() 61 
62         if user is None: 63             # 若是查詢的對象不存在。手工向form.username.errors追加一條錯誤信息,經過form顯示到前端頁面
64             form.username.errors.append('用戶或密碼錯誤') 65             return render_template('login_form.html', form=form) 66 
67         if check_password_hash(user.password, password): 68             # 若是密碼驗證經過。使用flask-login的login_user()完成保存登錄狀態的工做
69             # 登陸成功之後,須要將登陸狀態保存到session中,好比:session['uid']=user.id
70             login_user(user)
71 
72             # 得到跳轉鏈接,若是url中存在next跳轉參數,則跳轉到next頁面,不然跳轉到首頁
73             # 經過args獲取post請求中的URL的next參數信息
74             next_url = request.args.get('next') 75             return redirect(next_url or url_for('blue.index')) 76         else: 77             form.password.errors.append('用戶或密碼錯誤') 78             return render_template('login_form.html', form=form) 79     return render_template('login_form.html', form=form) 80 
81 
82 @bp.route("/form/index/",methods=['POST','GET']) 83 def index(): 84     return render_template("index.html") 85 
86 @login_manager.user_loader 87 def load_user(user_id): 88     return User.query.get(user_id)
 1 # 修改資源
 2 @app.route('/article/<article_id>/change/', methods=['POST', 'GET'])  3 def article_change(article_id):  4     article = Article.query.get(article_id)  5     # 根據 數據庫中查詢到的數據 建立 Form 對象
 6     # ArticleForm 內部會 將 article 對象的同名屬性設置到 ArticleForm 的同名屬性上
 7     # form.title = article.title
 8     # form.content = article.content
 9     # form.title.data
10     form = ArticleForm(obj=article) 11     if form.validate_on_submit(): 12         # 使用表單對象的 populate_obj 方法,用已驗證表單的內容來填充 Article 對象
13         # 將表單中提交過來的內容,再次反向綁定form上去
14         # article.title = form.title.data
15         # article.content = form.content.data
16  form.populate_obj(article) 17  db.session.commit() 18 
19         flash('文章保存成功') 20         return redirect(url_for('blue.article_list')) 21     return render_template('article-change.html', form=form)
修改資源
    • login_form.html
 1 <body>
 2 <form action="{{ url_for("blue.index") }}" method="post">
 3     {# <跨域訪問></防跨域訪問> #}  4 {{ form.csrf_token }}  5                              {# 登錄驗證失敗後: <從新顯示輸入的信息> </返回錯誤緣由> #}  6     用戶名:<input name="username" type="text" value="{{ form.username.data }}">{{ form.username.errors }}  7     密碼:<input name="password" type="password" value="">{{ form.password.errors }} 10     <input type="submit" value="submit">
11 </form>
12 </body>
    • register.html
 1 <body>
 2 <form action="" method="post">
 3     {# <csrf防跨域訪問></csrf防跨域訪問> #}  4  {{ form.csrf_token }}  5  {# flask-wtf 寫法 #}  6  {{ form.username.label }} {{ form.username() }} {{ form.username.errors }}  7  {{ form.password.label }} {{ form.password }} {{ form.password.errors }}  8  {{ form.password_confirm.label }} {{ form.password_confirm }} {{ form.password_confirm.errors }}  9     <input type="submit" value="submit">
10 </form>
11 </body>

緩存技術

方法

""" cache.cached:裝飾器,裝飾無參數函數,使得該函數結果能夠緩存 參數: timeout: 超時時間 key_prefix: 設置該函數的標誌 unless: 設置是否啓用緩存,若是爲True,不啓用緩存 forced_update: 設置緩存是否實時更新,若是爲True,不管是否過時都將更新緩存 query_string: 爲True時,緩存鍵是先將參數排序而後哈希的結果 cache.memoize:裝飾器,裝飾有參數函數,使得該函數結果能夠緩存 參數: make_name:設置函數的標誌,若是沒有就使用裝飾的函數 其餘參數同cached cache.delete_memoized:刪除緩存 參數: func_name:緩存函數的引用 *args:函數參數 """
# cache.clear()  # 清除緩存全部的緩存,這個操做須要慎重 # cache.get(key) # 獲取一個鍵的值,若是值是json格式會自動轉化成字典 # cache.set(key,value,timeout)     #設置一個鍵值,value能夠是字典,會自動轉化json格式的字符串 # cache.add(key, value, timeout=None) #設置一個鍵值,若是存在就pass,注意和set的區別 # cache.delete(key) #刪除鍵

流程

  

使用 

  • app/views.py
 1 import random  2 import time  3 from flask import Blueprint  4 from app.ext import cache  5 
 6 bp = Blueprint("blue",__name__)  7 
 8 # 緩存視圖函數 設置緩存。過時時間10秒
 9 @bp.route("/cache_views/") 10 @cache.cached(timeout=10) 11 def cache_views(): 12     """
13  當經過 cache.cached 緩存視圖函數時, 14  在超時以前(timeout<10)訪問此視圖函數,會先去去緩存中查找,返回緩存中的數據。 15  在超時以後(timeout>10)訪問此視圖函數,會去緩存中查找,查不到再去數據庫中查找,後保存在緩存中並返回數據。 16  :return: 例如:網站首頁,不常常變化的話,能夠將其存到緩存中 17     """
18     now = time.time() 19     return str(now) 20 
21 
22 # 緩存普通函數(單獨緩存某個函數,提供更好的複用性)
23 # 推薦指定key_prefix,緩存key的前綴。不然key爲調⽤的視圖函數所在的路由
24 @cache.cached(timeout=30, key_prefix='random_list') 25 def random_list():         # 隨機提取十個數字
26     return [random.randint(0, 100) for _ in range(10)] 27 
28 @bp.route('/random_view/') 29 def random_view(): 30     list0 = random_list()  # 獲取緩存中的十個數據
31     list1 = ",".join(map(str,list0)) 32     list2 = list1 + "------>" + str(random.randint(0, 100)) 33     return list2 34 
35 
36 # 緩存帶參函數
37 @cache.memoize(timeout=30,make_name="random_parm") 38 def random_parm(arg1, arg2): 39     return arg1 + arg2 + random.randint(0,10)
40 # 根據參數值 隨機獲取數值。參數不一樣 得到的隨機數不一樣,且互不影響 41 # http://127.0.0.1:5000/random_args/1/3/ 結果:4----->73 42 # http://127.0.0.1:5000/random_args/1/2/ 結果:6----->48 43 @bp.route("/random_args/<int:arg1>/<int:arg2>/") 44 def random_args(arg1,arg2): 45 return str(random_parm(arg1,arg2)) + "----->" + str(random.randint(0,100))
46 # 清理緩存。cache.delete(函數名,此函數參數,此函數參數) 47 @bp.route("/delete/<int:arg1>/<int:arg2>") 48 def delete(arg1,arg2): 49 cache.delete(random_parm,arg1,arg2) 51 return "ok" 52 53 54 # 緩存對象(鍵值對)。cache.set('鍵', '值', 過時時間) 55 @bp.route("/set_cache/") 56 def set_cache(): 57 cache.set('name', '老王', timeout=30) 58 cache.set('persion', {'name': '曉黎', 'age': 18}, timeout=30) 59 cache.set('lst', [1, 2, 3, 4], timeout=30) 60 # 模擬登陸成功後,把用戶身份信息保存到 session 61 session_id = '987654321' 62 cache.set(session_id, {'user_id': 123456}, timeout=1800) 63 64 print(cache.get('name')) 65 print(cache.get('persion')) 66 print(cache.get('lst')) 67 # 模擬 根據 session_id 獲取用戶的身份信息 68 print(cache.get(session_id)) 69 70 return "ok"

會話技術(cookie)

 出現緣由:HTTP是無狀態協議,使用的短鏈接,請求週期很是短。使用會話技術爲了數據能夠跨請求使用,讓服務器識別客戶端

 Cookie:Cookie客戶端會話技術,數據都存儲在瀏覽器中,默認攜帶本網站的全部Cookie。缺點:明文傳輸不安全

      Cookie以key-value存儲,支持過時,默認關閉瀏覽器即失效;不能跨瀏覽器,不能跨域名訪問

 

  • manage.py
1 from flask_script import Manager 2 from app import create_app 3 
4 app = create_app() 5 manager = Manager(app=app) 6 
7 if __name__ == '__main__': 8     manager.run()
  • app/__init__.py
1 from flask import Flask 2 from app import views 3 
4 def create_app(): 5     app = Flask(__name__)            # 實例化 Flask對象
6     app.register_blueprint(views.bp) # 將藍圖註冊到app上
7     return app                       # 返回出去 Flask實例
  • app/views.py
 1 from flask import Blueprint, request, render_template, make_response, redirect, url_for, abort  2 
 3 # 用藍圖管理路由,規劃url。參數("藍圖名字",__name__)
 4 # 藍圖必須了管理的視圖在一個文件中,否則不能使用
 5 bp = Blueprint("blue",__name__)  6 
 7 @bp.route('/index')  8 def index():  9     username = request.cookies.get('username','遊客') 10     return render_template("index.html",username= username) 11 
12 @bp.route('/login/',methods=['GET','POST']) 13 def login(): 14     if request.method == "POST": 15         username = request.form.get('username') 16         # 模擬登錄。使用redirect 來獲取響應對象。
17         response = redirect(url_for('blue.index')) 18         # 經過response對象設置cookie
19         response.set_cookie('username',username) 20         return response 21     # render_template(模版名稱,**context) **context是須要傳遞到模版中的 變量
22     return render_template('login.html') 23 
24 @bp.route('/logout/') 25 def logout(): 26     # 模擬登錄,使用redirect 來獲取響應對象。
27     response = redirect(url_for('blue.index')) 28     # 刪除cookie
29     response.delete_cookie('username') 30     return response
  • app/templates/index.html
 1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <title>index</title>
 6 </head>
 7 <body>
 8 <h2>歡迎:{{ username }}</h2>
 9 <form action="{{ url_for('blue.logout')}}" method="get">
10     <input type="submit" value="登出">
11 </form>
12 </body>
13 </html>
  • app/templates/login.html
 1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <title>Title</title>
 6 </head>
 7 <body>
 8 <form action="{{ url_for('blue.login')}}" method="post">
 9     <input type="text" name="username" value="" placeholder="請輸入用戶名">
10     <input type="submit" value="登陸">
11 </form>
12 </body>
13 </html>

會話技術(session)

 Session:服務端會話技術,數據都存儲在服務端

  一、當瀏覽器第一次訪問 web 服務器時,web 服務器會爲此瀏覽器生成一個 session,爲這個 session 建立一個惟一的 session_id;

  二、在服務器返回請求時,會向瀏覽器設置 cookies,cookies 中是 key-value 存儲reseponse.set_cookies('session_id', session_id, expire=)

  三、瀏覽器再次訪問此 web 服務器時,會在請求中帶上 cookies 信息,即:session_id: dsfksdlfj232wrwdsf 

  四、當 web 服務器在次接收到瀏覽器請求時,會從請求的 cookies 中提取 session_id 的值,

     而後根據 session_id 的值,查找到與當前瀏覽器匹配的 session(好比:從數據庫查詢等)

 繪畫特性:依賴於Cookie,以key-value存儲、相對安全、不能跨網站,不能跨域名、支持過時默認31天 -> 設置:session.permanent = True

   

  • manage.py
from flask_script import Manager from app import create_app app = create_app() manager = Manager(app=app) if __name__ == '__main__': manager.run()
  • app/__init__.py
import datetime from flask import Flask from flask_session import Session from app import views def create_app(): app = Flask(__name__) # 爲sesson設置一個密鑰key值。兩種方式,推薦第二種
    # app.secret_key = 'asdfghjkl'
    app.config['SECRET_KEY'] = 'd53a40dae292df9d409ef64e4a04905d'

    # flssk-session 擴展配置
    # 指定 flask-session 擴展將 session 數據持久化到 redis 中
    app.config['SESSION_TYPE'] = 'redis'

    # 指定 flask-session 存儲在 redis 中的 session id的前綴
    app.config['SESSION_KEY_PREFIX'] = 'flask:session'

    # 自定義 session 過時時間
    app.config['PERMANENT_SESSION_LIFETIME'] = datetime.timedelta(days=7) # 建立 flask-session 的 Session 對象
    sess = Session() # 將 flask-session 擴展初始化,跟app創建連接
    sess.init_app(app=app) app.register_blueprint(views.bp) # 註冊路由
    return app
  • app/views.py
from flask import Blueprint, render_template, redirect, url_for, request, session # Blueprint: 第一個參數爲藍圖自定義名稱,第二個參數是 Blueprint 對views.py 導入時須要的名稱。
bp = Blueprint('blue',__name__) """ 在 flask 項目中使用 session 1. 爲 flask 對象(app)設置secrt key 二、在任何視圖函數中均可以像使用字典同樣操做 session session['username'] = 'jack' 向session中增長一個 鍵值對 session.get('username') 從session中根據key獲取value session.pop('username') 從session中刪除指定的key """ @bp.route('/index/') def index(): # session.get 從 session 中根據key獲取對用的值。能夠像字典同樣操做
    username = session.get('username','遊客') return render_template('index.html',username=username) @bp.route('/login/',methods=["POST","GET"]) def login(): if request.method == 'POST': username = request.form.get('username') session['username'] = username return redirect(url_for('blue.index')) return render_template('login.html') @bp.route('/logout/') def logout(): session.pop('username') return redirect(url_for('blue.index'))
1 # 設置退出,
2 @app.route('/logout/') 3 def logout(): 4     response = Response('退出成功') 5     response.delete_cookie('session')  # 刪除session中的session參數
6     session.pop['username']            # 刪除session中的username參數值 推薦
7     del session['username']            # 刪除session中的username參數值 不存在,會報錯
8     return response
  • app/templates/login.html
 1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <title>Title</title>
 6 </head>
 7 <body>
 8 <form action="{{ url_for('blue.login')}}" method="post">
 9     <input type="text" name="username" value="" placeholder="請輸入用戶名">
10     <input type="submit" value="登陸">
11 </form>
12 </body>
13 </html>
  • app/templates/index.html
 1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <title>Title</title>
 6 </head>
 7 <body>
 8 <h2>歡迎:{{ username }}</h2>
 9 <form action="{{ url_for('blue.logout')}}" method="get">
10     <input type="submit" value="登出">
11 </form>
12 </body>
13 </html>
相關文章
相關標籤/搜索