Flask快速入门day 03(蓝图的使用,g对象,数据库连接池)
Flask框架
一、蓝图-blueprint
简介:
blueprint(蓝图)在flask项目中用来组织管理和注册视图函数的路由
蓝图实际可以理解为是一个存储一组视图方法的容器对象,其具有如下特点:
-
1、一个应用可以具有多个蓝图,可以将一个蓝图注册到任何一个未使用的URL下比如 “/user”、“/goods”
-
2、可以单独具有自己的模板、静态文件或者其它的通用操作方法,它并不是必须要实现应用的视图和函数的
-
3、在一个应用初始化时,就应该要注册需要使用的蓝图
-
4、蓝图并不是一个完整的应用,它不能独立于应用运行,而必须要注册到某一个应用中
1、蓝图的用法
- 1、在需要被注册的app文件,或py文件下导入
from flask import Blueprint
- 2、实例化蓝图
# 第一个参数视图别名
# 第二个参数模块别名
# 第三、四参数指定静态文件和模板路径
user_bp = Blueprint('user', __name__, static_folder='static', template_folder='templates')
- 3、在视图函数上装饰实例化的蓝图对象(不再直接使用flask实例化对象)
@user_bp.route('/', endpoint='index')
def index():
return 'index view'
- 4、使用falsk实例化的对象管理蓝图并注册路由
# 导入管理app的蓝图实例化对象
from .user import user_bp
# 注册路由 管理实例化的蓝图对象
app.register_blueprint(user_bp, url_prefix='/user')
2、蓝图规划目录
不使用蓝图规划目录:
# 不使用蓝图规划目录容易造成循环导入
-falsk # 项目文件
-src # 存放核心文件
__init__.py # 用于实例化flask,导入views
models.py # 用于创建表模型
views.py # 视图文件
-static # 静态文件
-templates # 模板文件
index.html # 模板
-manage.py # 项目启动文件
使用蓝图规划目录(小型项目):
# 使用蓝图,划分小型项目目录
little_blueprint # 项目名
-src # 核心代码
-static # 静态文件
-1.jpg # 图片
-templates # 模板文件
-user.html # 模板
-views # 视图函数存放位置
-order.py # 订单相关视图
-user.py # 用户相关视图
-__init__.py # 包
-models.py # 表模型
-manage.py # 启动文件
使用蓝图规划目录(大型项目):
falsk # 项目文件
src # 核心文件
home # 首页app
order # 订单app
user # 用户app
static # app下静态文件文件
templates # app下模板文件
__init__.py # 包(注册蓝图,管理app的地方)
models.py # app下表模型文件
views.py # 视图函数文件
__init__.py # 项目包文件(管理app,注册路由分发的地方)
settings.py # 项目配置文件
manage.py # 项目启动文件
二、g对象
简介:
-
g对象:
-
global的缩写,在python中是个关键字,不能以关键字作为变量名,干脆用了g
-
g对象,在整个请求的全局,可以放值,可以取值
-
g对象是flask提供的一个用于当初请求下的上下文,可以在当此请求下将一个对象或变量存入g对象,就可以在当此请求下的任何地方直接使用
-
-
为什么不直接使用request对象:
- 为例避免污染request中的方法
1、使用方法
- 1、 导入g对象
from flask import g
- 2、存入
# 直接使用‘点的’方式存入
g.name = name
- 3、取
# 直接使用‘点’取值
g.name
2、使用案例
from . import user_bp
from flask import request, g
# g对象的存取
@user_bp.route('/', endpoint='index')
def index():
# 获取get请求携带的name,存入g中然后在return出存入的值
name = request.args.get('name')
# 存入
g.name = name
# 取出
return g.name
@user_bp.route('/get', endpoint='get_name')
def get_name():
# 当次请求并没有存入,所以会直接报错
return g.name
三、数据库连接池
简介:
- 什么是连接池:
- 简单来说,类似于一个池塘,池塘的大小决定池塘内鱼儿的数量,也就是操作请求数据库的数量,每个人的请求都是一条新的链接
- 为什么要用连接池:
- 如果在视图函数内直接使用pymysql,那么每次请求都会建立一条新的数据库链接,使用连接池可以控制链接建立的链接数量
- 直接在全局建立链接可以吗:
- 不可以,直接在全局建立一条数据库连接的话,这样所有的请求都会使用这一条链接,假如a发起了一条seletc查询user数据库,在返回数据前b也使用了seletc查询order数据,这样a返回的数据就会变成b查询的结果,照成数据混乱
- 连接池解决的问题:
- 每次进入视图函数,从池中取一个连接使用,使用完放回到池中,只要控制池的大小,就能控制mysql连接数
1、不使用池
import pymysql
@user_bp.route('/', endpoint='index')
def index():
# 实例化pymysql
conn = pymysql.connect(user='root',
password="123",
host='127.0.0.1',
database='big_cabbage1',
port=3306)
# 产生游标对象(参数指定返回的格式是字典,默认是元组)
cursor = conn.cursor(pymysql.cursors.DictCursor)
# 查询数据库
cursor.execute('select * from user limit 2')
# 获取全部的查询数据
res = cursor.fetchall()
return jsonify(res)
2、使用连接池
# 使用第三方数据库连接池,使用步骤
-1 安装 pip install dbutils
-2 使用:实例化得到一个池对象
-3 在视图函数中导入使用
from dbutils.pooled_db import PooledDB
import pymysql
pool = PooledDB(
creator=pymysql, # 使用链接数据库的模块
maxconnections=10, # 连接池允许的最大连接数,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='',
database='cnblogs',
charset='utf8'
)
# 带池的代码
@app.route('/article_pool')
def article_pool():
conn = pool.connection()
cursor = conn.cursor(pymysql.cursors.DictCursor)
cursor.execute('select id,title,author_img from aritcle limit 2')
res = cursor.fetchall()
print(res)
return jsonify(res)
3、压力测试
# 压力测试代码
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()
## 效果是:
使用池的连接数明显小
不使用池连接数明显很大
# 查看数据库连接数
show status like 'Threads%'