蓝图、g对象、数据库连接池

一、蓝图(blueprint)

1、介绍与作用

我们的应用经常会有很多小模块,比如用户模块、后台管理模块等,虽然这些模块都在同一个应用中,但是功能大不相同,把他们放在同一个文件中,显得十分杂乱,不便于管理维护,那么有没有什么方法可以将模块分开管理呢?是有的!Flask 蓝图(Blueprint),它可以模块化管理路由,使用蓝图可以把不同模块的视图函数写在不同的py文件中,在主视图中导入分路由视图的模块,并注册蓝图对象,降低各个功能模块的耦合度使程序结构更加简单、清晰。

2、蓝图的使用

不用蓝图,划分目录

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

使用上述结构编写flask项目的时候需要注意,在src的双下init文件中需要导入views.py文件,这样内部的视图函数才会被注册

部分关键文件代码展示

manage.py

from src import app

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

src的双下init.py

from flask import Flask

app = Flask(__name__, template_folder='../templates', static_folder='../static')
app.debug = True
app.secret_key = 'asdfasdjfklewlogsfjaojsifj'
from . import views

ps:有没有感觉和django的目录结构很像

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

蓝图的使用步骤

第一步:导入蓝图类
from flask import Blueprint

第二步:实例化得到蓝图对象
us=Blueprint('user', __name__)

第三步:在app中注册蓝图
app.register_blueprint(us)

第四步:在不同的views.py 使用蓝图注册路由
@us.route('/login')

"""
补充:蓝图可以有自己的静态文件和模板
补充:注册蓝图时,可以使用前缀,必须以/开头
"""

划分目录

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

manage.py

from src import app

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

src的双下init.py

from flask import Flask

app = Flask(__name__)
app.debug = True
app.secret_key = 'asdfasdjfklewlogsfjaojsifj'
from .views.user import user_bp
from .views.order import order_bp

app.register_blueprint(user_bp)
app.register_blueprint(order_bp)

user.py

from src import app
from flask import Blueprint, render_template

user_bp = Blueprint('user', __name__)

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


@app.route('/home')
def user_home():
    return render_template('home.html', name='zzh')

4、使用蓝图划分大型项目目录

# 使用蓝图,划分大型项目目录  分成多个app,像django一样
-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								# 启动文件

我们在编写大型项目目录的时候把蓝图对象的创建放到了每个app文件夹内的双下init文件中,我们需要在其内部导入包内的views.py文件,执行视图的路由注册

在注册蓝图对象的时候,可以设置蓝图的路由前缀,使用的属性如下(必须要在前面带上斜杠):

url_prefix='/admin'

部分关键文件代码展示

manage.py

from src import app

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

src的双下init.py

from flask import Flask

app = Flask(__name__)

app.config.from_pyfile('settings.py')

from .admin import admin_bp
# from .home import home_bp
# from .order import order_bp

app.register_blueprint(admin_bp, url_prefix='/admin')
# app.register_blueprint(home_bp, url_prefix='home')
# app.register_blueprint(order_bp, url_prefix='order')

admin app的双下init.py

from flask import Blueprint

admin_bp = Blueprint('admin', __name__, static_folder='static', template_folder='templates')

from . import views

admin app的views.py

from flask import render_template
from . import admin_bp


@admin_bp.route('/home')
def home():
    return render_template('/home.html')

5、其他知识点

当我们使用蓝图的时候,可以在每个视图内使用请求扩展,他只作用于当前的视图(用蓝图对象去注册请求扩展方法),如果我们想把请求扩展用于全局,就是使用app(Flask对象)去注册

二、g对象

1、g对象是什么?

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

g对象是个全局变量,在任意的位置导入使用即可,在整个请求的全局,可以放值,可以取值

2、作用

为什么不学django使用request作为上下文【因为使用request,可能会造成request数据的污染,不小心改了request的属性,但你不知道】

防止和 request 内部的属性混乱,比如不知道 request 里面有没有 name 属性,可以直接 g.name 设值。只对这个请求设值

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

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

3、g和session有什么区别?

  • g是只针对当次请求

  • session针对于多次请求

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就是这么做的)

  • 把连接对象,做成全局的,在视图函数中,使用全局的连接,查询,返回给前端

    存在问题:会出现数据错乱,详见下图

    ppo9fiQ.png

    带池的代码

    @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)
    

    不带池的代码

    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)
    

    压力测试代码

    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%'
    
posted @ 2023-04-06 15:49  dear丹  阅读(43)  评论(0)    收藏  举报