109、蓝图、flask-session、数据库连接池

287 阅读6分钟

今日内容概要

  • 蓝图
  • flask-session
  • 数据库连接池

今日内容详情

蓝图

1.蓝图blueprint:对程序进行目录结构划分
2.不用蓝图,划分目录--->一直使用app对象,会出现循环导入的问题

不用蓝图,划分目录

flask_day05
  -templates
  	--order.html
  -views
    --__init__.py
    --goods.py
    --order.py
    --user.py
  -manage.py

manage.py

from views import app

if __name__ == '__main__':
    app.run()

init.py

from flask import Flask

app = Flask(__name__,template_folder='../templates')

#不导入这个不行
from . import user
from . import order
from . import goods

goods.py

from . import app

@app.route('/goods')
def goods():
    return 'goods'

order.py

from . import app
from flask import render_template

@app.route('/order')
def order():
    return render_template('order.html')

user.py

from . import app

@app.route('/')
def home():
    return 'home'

@app.route('/user')
def user():
    return 'user'

使用蓝图

1.实例化得到一个蓝图对象      order_blue=Blueprint('order',__name__,template_folder='../templates')
2.以后注册路由,写请求扩展,都使用蓝图
  @user_blue.before_request
  @user_blue.route('/register')
3.在app中注册蓝图
  from . import user
  app.register_blueprint(user.user_blue)   app.register_blueprint(user.user_blue,url_prefix='/user')
flask_day05
  -templates
  	--order.html
  -views
    --__init__.py
    --goods.py
    --order.py
    --user.py
  -manage.py

manage.py

from views import app

if __name__ == '__main__':
    app.run(port=8080)

init.py

from flask import Flask

# app = Flask(__name__,template_folder='../templates')
# app = Flask(__name__,static_folder='../static')
app = Flask(__name__)
app.debug = True
app.secret_key = 'asfasdfasdf'

#不导入这个不行
from . import user
from . import order
from . import goods
# 3.注册蓝图
app.register_blueprint(user.user_blue,url_prefix='/user')  # 路由前缀
app.register_blueprint(order.order_blue,url_prefix='/order')  # 路由前缀

user.py

from flask import Blueprint
# 1.首先实例华得到蓝图对象
user_blue = Blueprint('user',__name__)

# 2.其次注册路由
@user_blue.route('/')
def home():
    return 'home'

@user_blue.route('/user')
def user():
    return 'user'

order.py


from . import app
from flask import render_template,Blueprint

order_blue=Blueprint('order',__name__,template_folder='../templates',static_folder='../static')


@order_blue.route('/order')
def order():
    return render_template('order.html')

order.html

<body>
<h1>order order</h1>
<img src="/order/static/7.jpg" alt="失败">
</body>

蓝图小项目

flask_blueprint_little  #  项目名
	-src                # 核心文件
        --__init__.py     #包的inin里面实例化得到app对象
        --views           # 视图函数,类
            ---user.py
            ---order.py
        --templates       #模板
            ---user.html
        --static         #静态文件
    -manage.py          #启动文件

蓝图大型项目

flask5.png

Flask_session

1.flask 自带session--->以cookie的形式放到了浏览器中--->加密
2.真正的session,是在服务端存储
	django中存在djangosession表中
	flask中,使用第三方,保存在--->redis中--->flask-session
3.flask能不能用jwt--->能--->flask-session
4.使用:pip3 install flask-session

  

flask6.png

使用

方式一

	1.pip3 install flask-session
 
  #降一下flask版本即可
  # 用高版本:在app中放一个参数  			app.session_cookie_name='session'

1.使用方式一:
    from flask_session import RedisSessionInterface
    app.session_cookie_name='session'
    app.session_interface=RedisSessionInterface(redis=None,key_prefix='lqz')  # 动态替换,把原来的session对象换成放到redis的session对象
    # 4 以后再使用session,就会存到redis中了
    session.get()
    session[]=value赋值
    
from flask import Flask,session

# 1.导入类
from flask_session import RedisSessionInterface

app = Flask(__name__)
app.debug = True
app.secret_key = 'sdsfcdzfcsfvc'

# 2.实例话得到对象

# 3.把实例化得到的对象,赋值给app.session_interface
import redis
conn = redis.Redis(host='127.0.0.1', port=6379)

app.session_interface=RedisSessionInterface(redis=conn, key_prefix='nana') # 动态替换,把原来的session对象换成放到redis的session对象



# 4 以后再使用session,就会存到redis中了
@app.route('/')
def index():

    session['name']="luona"

    return 'index'

@app.route('/home')
def home():
    print(session['name'])
    return 'home'


if __name__ == '__main__':
    app.run()

使用方式二:

	from redis import Redis
    from flask_session import Session
    app.session_cookie_name = 'session'
    app.config['SESSION_TYPE'] = 'redis'
    app.config['SESSION_REDIS'] = Redis(host='127.0.0.1',port='6379')
    Session(app)
from flask import Flask,session

app = Flask(__name__)
app.debug = True
app.secret_key = 'sdsfcdzfcsfvc'

from redis import Redis
from flask_session import Session
# app.session_cookie_name = 'session'
app.config['SESSION_TYPE'] = 'redis'
app.config['SESSION_REDIS'] = Redis(host='127.0.0.1',port='6379')
Session(app)

# 4 以后再使用session,就会存到redis中了
@app.route('/')
def index():

    session['name']="cx"

    return 'index'
@app.route('/home')
def home():
    print(session['name'])
    return 'home'

if __name__ == '__main__':
    app.run()

数据库连接池

flask--->数据库--->原生操作--->pymsql

flask7.png

1.安装:DBUtils
2.使用 类创建一个池对象
    PYMYSQL_POOL = PooledDB(
        creator=pymysql,  # 使用链接数据库的模块
        maxconnections=2,  # 连接池允许的最大连接数,0和None表示不限制连接数
        mincached=1,  # 初始化时,链接池中至少创建的空闲的链接,0表示不创建
        maxcached=0,  # 链接池中最多闲置的链接,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='cars',
        charset='utf8'
    )
3.从池对象中,取出一个链接使用
	conn = PYMYSQL_POOL.connection()

4.flask中使用
  @app.route('/')
  def index():
      conn = PYMYSQL_POOL.connection()  # 从池中拿一个链接
      cursor = conn.cursor(cursor=DictCursor)  # 默认元组套元组,设置DictCursor就是列表套字典
      cursor.execute('select id,title from news where id<10')
      res1 = cursor.fetchall()
      cursor.close()
      conn.close()
      return jsonify(res1)
    

flask数据库操作

from flask import Flask,jsonify
import pymysql


app = Flask(__name__)
app.debug = True
app.secret_key = 'sdsfcdzfcsfvc'
from pymysql.cursors import DictCursor


@app.route('/')
def index():
    # 1.conn连接的创建,放到函数里面,否则会数据错乱
    conn = pymysql.connect(
        user='root',  # The first four arguments is based on DB-API 2.0 recommendation.
        password="ln1998151125",
        host='127.0.0.1',
        database='jingdong',
        unix_socket=None,
        port=0,
    )
    curser = conn.cursor(cursor=DictCursor)  #  # 默认元组套元组,设置DictCursor就是列表套字典
    curser.execute('select * from test where id<10')
    res = curser.fetchall()
    print(res)
    curser.close()
    conn.close()
    return jsonify(res)

if __name__ == '__main__':
    app.run()

1.conn和Cursor是全局--->会出数据错乱,详情看图
2.conn和Cursor要在视图函数中--->独立生成--->django,执行一个orm--->创建一个链接,执行,执行完释放链接--->假设并发数很高--->需要使用数据库连接池

数据库连接池

无连接池

from threading import Thread
import pymysql
from pymysql.cursors import DictCursor
import time
import random

# 无连接池
def task():
    conn = pymysql.connect(
        user='root',  # The first four arguments is based on DB-API 2.0 recommendation.
        password="123",
        host='127.0.0.1',
        database='jingdong',
        unix_socket=None,
        port=0,
    )
    curser = conn.cursor(cursor=DictCursor)  #  # 默认元组套元组,设置DictCursor就是列表套字典
    time.sleep(random.randint(0,2))
    curser.execute('select * from test where id<10')
    res = curser.execute("show status like 'Threads%'")
    curser.fetchall()
    print(res)

    curser.close()
    conn.close()


l =[]
for i in range(300):
    t = Thread(target=task)
    t.start()
    l.append(t)

for i in l:
    l.join()

连接池

Pool.py

from dbutils.pooled_db import PooledDB
import pymysql

# 池大小为6的数据库连接池---》
PYMYSQL_POOL = PooledDB(
    creator=pymysql,  # 使用链接数据库的模块
    maxconnections=2,  # 连接池允许的最大连接数,0和None表示不限制连接数
    mincached=1,  # 初始化时,链接池中至少创建的空闲的链接,0表示不创建
    maxcached=0,  # 链接池中最多闲置的链接,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='jingdong',
    charset='utf8'
)


from flask import Flask,jsonify
import pymysql
from pymysql.cursors import DictCursor
from pool import PYMYSQL_POOL

#
app = Flask(__name__)
app.debug = True
app.secret_key = 'sdsfcdzfcsfvc'


@app.route('/')
def index():
    conn = PYMYSQL_POOL.connection()  # 从池中拿一个链接
    cursor = conn.cursor(cursor=DictCursor)  # 默认元组套元组,设置DictCursor就是列表套字典
    cursor.execute('select * from test where id<10')
    res1=cursor.fetchall()
    cursor.execute("show status like 'Threads%'")
    res = cursor.fetchall()
    print(res)
    cursor.close()
    conn.close()
    return jsonify(res1)

@app.route('/no_pool')
def home():
    conn = pymysql.connect(
        user='root',
        password="ln1998151125",
        host='127.0.0.1',
        port=3306,
        database='jingdong')
    cursor = conn.cursor(cursor=DictCursor)  # 默认元组套元组,设置DictCursor就是列表套字典
    cursor.execute('select * from test where id<10')
    res1 =cursor.fetchall()
    cursor.execute("show status like 'Threads%'")
    res = cursor.fetchall()
    print(res,'---')
    cursor.close()
    conn.close()
    return jsonify(res1)

if __name__ == '__main__':
    app.run()

request并发请求


from threading import Thread
import requests

def task():
    # res = requests.get('http://127.0.0.1:5000')
    """
    [{'Variable_name': 'Threads_cached', 'Value': '9'}, {'Variable_name': 'Threads_connected', 'Value': '7'}, {'Variable_name': 'Threads_created', 'Value': '691'}, {'Variable_name': 'Threads_running', 'Value': '4'}]
    
    :return: 
    """
    res = requests.get('http://127.0.0.1:5000/no_pool')
    """
    [{'Variable_name': 'Threads_cached', 'Value': '9'}, {'Variable_name': 'Threads_connected', 'Value': '9'}, {'Variable_name': 'Threads_created', 'Value': '714'}, {'Variable_name': 'Threads_running', 'Value': '2'}] ---
    """
    print(len(res.text))

if __name__ == '__main__':
    for i in range(500):
        t = Thread(target=task)
        t.start()