蓝图,g对象,数据库链接池

发布时间 2023-04-04 15:03:02作者: 李阿鸡

flask蓝图使用

blueprint 翻译后称之为蓝图。

作用是: 用来划分目录

​ 之前写项目的时候全在一个py文件内写flask项目。 需要使用蓝图来划分目录。小型项目与大型目录都可以

蓝图使用

1 导入蓝图类 业务视图里

from flask import Blueprint

2 实例化得到蓝图对象 业务视图里

us = blueprint('user',__name__)

3.在app的__init__注册蓝图 包 __init__ 中实例化得到Flask对象

导入视图类的蓝图
from .views.user import user_bp
app.register_blueprint(user_bp)

4在不同的app里 使用蓝图注册路由 业务视图里

@us.route('/login')
def login():
    pass

小型项目就按上述操作

目录

    little_blueprint              # 项目名
        -src                      # 核心代码
            -static               # 静态文件
                -1.jpg            # 图片
            -templates            # 模板文件
            -user.html            # 模板
            -views                # 视图函数存放位置
                -order.py         # 订单相关视图
                -user.py          # 用户相关视图
            -__init__.py          # 包
            -models.py            # 表模型
        -manage.py                # 启动文件

补充:

5 多个app目录可以 在 蓝图设置前缀

app.register_blueprint(user_bp,url_prefix='/user')

6 多个app目录自己的template与static 不与别的app目录起冲突可以按下面这样设置

user_bp = Blueprint('user', __name__, template_folder='templates', static_folder='static')

大型项目需每个功能弄一个文件夹,在文件夹类有 static,templates,__init__,views,models ,其他一样操作。

目录

big_blueprint  								# 项目名
    -src									# 核心文件
        -admin								# admin的app
        	-static							# 静态文件
        		-1.jpg						# 图片
        	-templates						# 模板文件目录
        		-admin_home.html			# 模板文件
        	-__init__.py					# 包
        	-models.py						# 表模型
        	-views.py						# 视图函数
        -home								# home app
        -order								# orderapp
        -__init__.py						# 包
        -settings.py						# 配置文件
    -manage.py								# 启动文件

g对象

为什么用单字母来命名:

​ g是global的缩写,global在python中是一个关键字,不能以关键字作为变量名。

在整个请求的全局,可以对它进行放值,也可以取值当次请求生效

与我们之前写的路飞商城项目 中的 context 功能一样。

g对象是全局的在任意位置导入就可使用

from flask import Flask, g

app = Flask(__name__)
app.debug = True

def add(a, b):
    print(g.name) # 并没有传name过来,可以发现g是全局的
    return a + b

@app.route('/')
def home():
    g.name = 'zhangsan' # 也可以从request中获取name g.name = request.args.get('name')
    res = add(1, 2)
    print(res)
    return 'Hello World!'

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

数据库的连接池

flask操作mysql 也是使用pymysql

from flask import Flask,jsonify
import pymysql

app = Flask(__name__)
app.debug = True


@app.route('/article')
def article():
    # 从mysql中的article表中获取数据
    # 1.连接数据库
    conn = pymysql.connect(user='root',
                           password="",
                           host='127.0.0.1',
                           database='cnblogs',
                           port=3306, )
    # 2.创建游标      
    cursor = conn.cursor()  #设置游标的类型为字典类型 cursor = conn.cursor(pymysql.cursors.DictCursor)
    # 3.执行sql语句
    cursor.execute('select id,title from article limit 2')
    # 4.获取数据
    res = cursor.fetchall()
    #关闭链接
    cursor.close()
    conn.close()
    print(res)   # 数据是元组套元组的形式
    return jsonify(res)  # 将数据转换成json格式的数据返给前端


if __name__ == '__main__':
    app.run()
  
"""	
有问题
   一个请求就会创建一个链接,请求结束,链接关闭。
在全局设置链接会有问题,用的都是一个请求。
	如果用并发操作查询数据,2个请求都查询了,但都没取,过一会取了会出现数据错乱
"""

image

解决上述两个问题

使用数据库的链接池

每次进入视图从池里取一个链接使用,使用完放回去。控制池的大小就能控制mysql的链接数

需要借助于第三方模块

pip install dbutils

使用

实例化得到池对象

from dbutils.pooled_db import PooledDB
import pymysql
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=[], #开始会话前执行的命令列表。
    ping=0,         #ping MySQL服务端,检查是否服务可用。
    host='',
    user='',
    password='',
    database='',
    port=3306,
    charset='utf8',

)

在视图中使用池

from flask import Flask,jsonify
import pymysql
from POOL import pool

app = Flask(__name__)
app.debug = True

@app.route('/article')
def article():
    # 从池中获取一个连接
    conn= pool.connection()
    # 产生游标
    cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
    # 执行sql
    cursor.execute('select * from article')
    # 获取数据
    res = cursor.fetchall()
    #关闭链接
    cursor.close()
    conn.close()
    print(res)   # 数据是元组套元组的形式
    return jsonify(res)  # 将数据转换成json格式的数据返给前端

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

数据库查询链接数量命令

show status like 'Threads%'

压力测试代码

from threading import Thread
import requests


def task():
    res = requests.get('http://127.0.0.1:5000/article_pool')
    print(len(res.text))


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

	 使用池的连接数明显小
    不使用池连接数明显很大