flask_day03:蓝图的使用、g对象、数据库连接池

回顾

1.cbv的使用
	写一个类继承MethodView,写get、post。。。
 	类属性decorators = [auth,] 可以加装饰器
  
2.cbv执行流程
	2.1 跟Django流程一样
  2.2 endpoint作用路径别名,add_url_rule(view_func=IndexView.as_view('index'))
  2.3 为什么endpoint不传,是被路由装饰器的函数名:函数.__name__
  2.4 装饰器的执行先后顺序
  
3.请求响应
	请求:全局request对象,在不同视图函数中尽管使用,不会错乱
  method
  path
  files
  form
  argvs。。。
  响应:四件套,响应对象,make_response包裹一下四件套之一
  set_cookies
  响应对象.headers 响应头
 
4.session使用
	设置秘钥
  全局导入,直接赋值,取值
  
5.session执行流程
	open_session: 前端写到cookie到后端,后端取出cookie对应的value值,解密,转到session兑对象中,后续再视图函数中,使用session即可
  save_session: 请求走的时候,校验session有没有被改过,如果被改了,删除cookie,重新设置cookie。session改了就删除cookie,没改就用原来的,而在Django是修改session表中的value值。
    
  session用起来像字典 --->>> 如何做,一个对象可以像字典一样使用,__getitem__ __setitem__,只要调用__setitem__就说明动了,对象属性modify,一开始false,只要触发了__setiten__,置为true,后期只要判断modify,就可以判断session有没有被改过

  
6.闪现;跨域请求获取到之前请求存放的数据,取一次就没了     关注一下Django的message框架
	flash('%s,对不起'% name)
  get_flashed_messages()
  
7. 请求扩展
	before_request
  after_request
  before_first_request
  teardown_request: 错误日志记录
  errorhandler:是某种状态码,就会执行它

蓝图的使用

blueprint 翻译过来的,称之为蓝图

作用是:之前全在一个py中写flask项目中,后期肯定要划分目录

不用蓝图,划分目录

no_blueprint			# 项目名
	src						 # 核心源码位置
  	__init__			# 包 里面实例化得到了app对象
    models.py			# 放表模型
    views.py			# 放视图函数
  static					# 放静态资源
  templates				# 放模板
  	home.html			# 模板
  manage.py				# 启动文件

image-20230404171453743

蓝图的使用步骤

第一步:导入蓝图类

flask import Blueprint

第二步:实例化得到蓝图对象

us=Blueprint('user', __name__)

第三步:在app中注册蓝图

app.register_blueprint(us)

第四步:在不同views.py 使用蓝图注册路由

@us.route('/login')
补充:蓝图可以有自己的静态文件和模板
补充:注册蓝图时,可以使用前缀,必须以/ 开头

使用蓝图,划分小型项目目录

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

image-20230404182003497

image-20230404181240332

使用蓝图,划分大型项目目录

有多个app,像Django一样

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

image-20230405105222463

image-20230405104900026

image-20230405110123637

g对象

g对象是什么?

专门用来储存用户信息的g对象,g的全称为global

global的缩写,再python中是个关键字,不能以关键字作为变量名,干脆就用了g。

  • g 对象,在整个请求的全局,可以放值,可以取值

  • 全局变量,在任意位置导入使用即可

它什么不学Django中使用request作为上下文?

  • 因为使用request,可能会造成request数据的污染,不就会小心改了request的属性,而却发现不了

  • 建议使用g是空的,放入之后在当次请求中全局优先

  • 以后想在当次请求中,放入一些数据,供后面使用,就可以使用g对象

g和session有什么区别?

  • g 是只针对与当次请求,而session是针对于多次请求

  • 解释:

    session对象是可以跨request的,只要session还未失效,不同的request的请求会获取到同一个session,但是g对象不是,g对象不需要管过期时间,请求一次就g对象就改变了一次,或者重新赋值了一次

代码:

from flask import Flask, g, request

app = Flask(__name__)
app.debug = True


@app.before_request
def before():
    if 'home' in request.path:
        g.xx = 'xx'


def add(a, b):
    # print('---',g.name)
    print('---', request.name)
    return a + b


@app.route('/')
def index():
    print(g.xx)
    name = request.args.get('name')
    # g.name = name
    request.method = name
    res = add(1, 2)
    print(res)
    return 'index'


@app.route('/home')
def home():
    print(g.xx)
    return 'index'


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

数据库连接池

flask操作mysql

# 使用pymysql
	在视图函数中,创建pymysql的连接,查数据,查完,返回给前端
  	问题一:这样会有什么问题呢?这样会导致来一个请求,创建一个连接,请求结束,连接关闭(Django就是这么做的)
    
  把连接对象,做成全局的,在视图函数中,使用全局的连接,查询,返回给前端
  	问题二:这样会有什么问题呢?会出现数据错乱,详见下图

演示问题一

在视图函数中,创建pymysql的连接,查数据,查完,返回给前端

如下图返回形式可以是是列表套字典,就可以简单快速生成一个简单的接口了,也不用在序列化了已经是列表套字典了,直接jsonify返回给前端就OK了
image

image-20230404185703523

演示问题二

测试全局连接结果数据错乱问题

import pymysql
import threading
import time
 
conn = pymysql.connect(user='root',
                       password="root",
                       host='127.0.0.1',
                       database='luffy01',
                       port=3306)
 
cursor = conn.cursor(pymysql.cursors.DictCursor)
 
 
def task_1():
    cursor.execute('select * from luffy_user')
    time.sleep(3)
    res = cursor.fetchall()
    print(res, "这是user表的数据")
 
 
def task_2():
    time.sleep(1)
    cursor.execute('select * from luffy_banner')
    time.sleep(5)
    res = cursor.fetchall()
    print(res, '这是banner表的数据')
 
 
if __name__ == '__main__':
    t1 = threading.Thread(target=task_1)
    t2 = threading.Thread(target=task_2)
    t1.start()
    t2.start()
 

下图数据出现错乱:

当两个请求过来时,第一个请求来时去查的banner数据,但查完没fetchall去取,第二个请求来了又去查了use数据,查完了。那第一个请求取,结果取了user的数据,而第二个确空了没有了,导致的数据错乱,这就是因为使用了全局的cursor导致

image-20230404185228226

  • 解决上面的两个问题

    数据库连接池

    1.创建一个全局的池

    2.每次进入视图函数,从池中取一个连接使用,使用完放回池中,只要控制池的大小,就能控制mysql的连接数

使用第三方数据库连接池

使用步骤

1.安装 pip install dbutils

2.使用:实例化得到一个池对象

3.在视图函数中导入使用

conn = pool.connection()
cursor = conn.cursor(pymysql.cursors.DictCursor)
cursor.execute('select id,title,author_img from aritcle limit 2')
res = cursor.fetchall()

POOL.py

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='root',
    database='luffy01',
    charset='utf8'
)

在视图函数中导入使用

from flask import Flask, g, request, jsonify
import pymysql

app = Flask(__name__)
app.debug = True


import time
import random
from POOL import pool

# 用池的代码
@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)

# 不用池的代码
@app.route('/article')
def article():
    conn = pymysql.connect(user='root',
                           password="",
                           host='127.0.0.1',
                           database='cnblogs',
                           port=3306)
    cursor = conn.cursor(pymysql.cursors.DictCursor)
    time.sleep(random.randint(1,3))
    cursor.execute('select id,title,author_img from aritcle limit 2')
    res = cursor.fetchall()
    cursor.close()
    conn.close()
    return jsonify(res)


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

压力测试

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%'

-teardown_request 错误日志记录

-errorhandler 监听状态码

不用蓝图划分目录导来到去肯定会出现循环导入

image-20230404103728380

posted @   小福福  阅读(51)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
  1. 1 原来你也在这儿 温余福
  2. 2 世间美好和你环环扣扣 温余福
  3. 3 随风起舞 温余福
  4. 4 罪恶都市 温余福
罪恶都市 - 温余福
00:00 / 00:00
An audio error has occurred, player will skip forward in 2 seconds.

作词 : 王星

作曲 : 灰鸿啊/皮皮

编曲 : 夏日入侵企画

制作人 : 邢硕

节奏吉他 : 肯尼

主音吉他 : 张伟楠

贝斯 : 皮皮

鼓 : 海鑫

和声 : 邢硕

音效制作 : 邢硕

录音 : 邢硕/夏国兴

混音 : 于昊

特别鸣谢 : 张伟楠

这城市的车流和这地表的颤抖

像一颗石子落入地心之后泛起的温柔

暗涌

河水流过转角她的楼

被梦魇

轻声呓语唤醒身后的幼兽

失效感官焦灼只剩下

麻木愚钝无从感受

共同支撑全都瓦解

只是我们现在都

已忘记到底是

谁隐藏春秋

谁在大雨之后

把旗帜插在最高的楼

过去陈旧的还在坚守

内心已腐朽

摇摇欲坠不停退后

毁灭即拯救

夏日掠夺春秋

结局无法看透

眼看这情节开始变旧

所有的城池已失守

最终无法占有

无眠辗转

伴着人间破碎的旧梦

像繁星

退却后只剩下混沌的夜空

炙热

掩盖风声鹤唳的担忧

把所有失落无助反手推入

无尽的白昼

失效感官焦灼只剩下

麻木愚钝无从感受

共同支撑全都瓦解

只是我们现在都已经忘记到底是

谁隐藏春秋

谁在大雨之后

把旗帜插在最高的楼

过去的陈旧还在坚守

内心已腐朽

摇摇欲坠不停退后

毁灭即拯救

夏日掠夺春秋

结局无法看透

眼看这情节开始变旧

所有的城池早已失守

惶恐难以接受

缠绵往复不肯放手

最终无法占有

谁隐藏春秋

谁在大雨之后

把旗帜插在最高的楼

过去的陈旧还在坚守

内心已腐朽

摇摇欲坠不停退后

毁 灭 即 拯 救

谁掠夺春秋

谁在大雨之后

把旗帜插在最高的楼

过去的陈旧还在坚守

内心已腐朽

摇摇欲坠不停退后

毁灭即拯救

夏日掠夺春秋

结局无法看透

明知城池已失守

缠绵往复不肯放手

最终无法占有

点击右上角即可分享
微信分享提示