首页 > 数据库 >flask-day3——蓝图的使用、g对象、数据库连接池

flask-day3——蓝图的使用、g对象、数据库连接池

时间:2023-04-04 17:57:31浏览次数:26  
标签:__ 蓝图 name flask app py day3 import 连接池

目录

一、蓝图(blueprint)

1、蓝图介绍

在Flask中,使用蓝图Blueprint来分模块组织管理。
蓝图实际可以理解为是一个存储一组视图方法的容器对象,其具有如下特点:

  • 一个应用可以具有多个蓝图(Blueprint)可以将一个蓝图(Blueprint)注册到任何一个未使用的URL下比如 “/user”、“/goods”

  • 蓝图(Blueprint)可以单独具有自己的模板、静态文件或者其它的通用操作方法,它并不是必须要实现应用的视图和函数的

  • 在一个应用初始化时,就应该要注册需要使用的蓝图(Blueprint)

  • 但是一个蓝图(Blueprint)并不是一个完整的应用,它不能独立于应用运行,而必须要注册到某一个应用中

2、蓝图的使用

不用蓝图,划分目录

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

ps:使用上述结构编写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

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								# 启动文件

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

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

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对象

g对象是专门用来存储用户信息的

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

g对象在一次请求中的全局(所有地方的代码),都是可以使用的可以放值,可以取值

g 对象相当于一个全局变量,在任意位置导入使用即可

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

  • 因为使用request,可能会造成request数据的污染,不小心改了request的属性,但你不知道
  • 建议使用g对象,因为他是空的,放入数据之后在当次请求中全局有效

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

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模块

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

app = Flask(__name__)
app.debug = True

# @app.route('/article')
# def article():
#     # 从mysql的cnblogs库的article表中取出两条数据
#     conn = pymysql.connect(user='root',
#                            password="",
#                            host='127.0.0.1',
#                            database='cnblogs',
#                            port=3306)
#     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)

# 单例
conn = pymysql.connect(user='root',
                       password="",
                       host='127.0.0.1',
                       database='cnblogs',
                       port=3306)
cursor = conn.cursor(pymysql.cursors.DictCursor)


@app.route('/article')
def article():
    # 从mysql的cnblogs库的article表中取出两条数据
    cursor.execute('select id,title,author_img from aritcle limit 2')
    res=cursor.fetchall()
    print(res)
    return jsonify(res)

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

简单使用:在视图函数中,创建pymysql的连接,查数据,查完,返回给前端(来一个请求,创建一个连接,请求结束,连接关闭,djanog就是这么做的)

有什么问题?

  • 会出现连接数过多的情况

如果我们把连接对象,做成全局的,在视图函数中,使用全局的连接,查询,返回给前端,就可以解决上面的问题,但是也有其他问题出现了

有什么问题?

image

  • 会出现数据错乱,详见上图

简单来说就是连接对象不能做成单例模式,单例模式下会出现数据混乱(因为要执行下一条查询语句,而来不及返回查询结果)

使用数据库连接池操作数据库

为了解决上面的两个问题,方案如下:

	-使用数据库连接池
    -创建一个全局的池
    -每次进入视图函数,从池中取一个连接使用,使用完放回到池中,只要控制池的大小,就能控制mysql连接数

使用数据库连接池需要安装第三方数据库连接池模块

pip install dbutils

创建数据库连接池对象

ps:需要使用pymysql

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

在视图函数中导入使用

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

效果:

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

查看数据库连接数的sql语句

show status like 'Threads%'

四、作业

1、什么是gil锁,有什么作用

GIL:又称全局解释器锁。作用就是限制多线程同时执行,保证同一时间内只有一个线程在执行。

线程非独立的,所以同一进程里线程是数据共享,当各个线程访问数据资源时会出现“竞争”状态,即数据可能会同时被多个线程占用,造成数据混乱,这就是线程的不安全。所以引进了互斥锁,确保某段关键代码、共享数据只能由一个线程从头到尾完整地执行。

image

2、python的垃圾回收机制是什么样的

机制讲解

当我们在运行程序时,很多的数据值会被闲置,得不到使用,这时就需要把这些无用的数据清除。在一些语言中,程序员需要自己编写代码删除这些无用的数据,但是python中不需要我们这么做,因此我们只需要了解python中垃圾回收机制的原理和运行方式。

共有三种机制

1、引用计数

当我们把一个变量名与数据值绑定的时候,python中会有数据存储数据值被引用的次数,这就是引用计数。当我们把变量名跟其他数据值绑定的时候,如果数据值的引用计数变成了0,那么在内存空间中就会把他删除,节省内存空间。

2、循环引用(标记清除)

当学习了引用计数后我们可以得知每次与变量名绑定,数据值都会增加一次引用计数,这里我们可以举个例子来说明循环引用:

3、分代回收

分代回收就是垃圾回收机制运行时,不对所有目标进行频繁检测,对于使用频率高的目标降低检测频率。

当python运行垃圾回收机制的时候,如果频繁运行,同样会占用大量的内存资源。这个时候就体现了分代回收的用处。

3、解释为什么计算密集型用多进程,io密集型用多线程


标签:__,蓝图,name,flask,app,py,day3,import,连接池
From: https://www.cnblogs.com/zhihuanzzh/p/17287225.html

相关文章

  • flask:Flask 和pythonweb框架介绍、flask快速使用、登录,显示用户信息小案例、配置文件
    目录一、Flask和pythonweb框架介绍1.1pythonweb框架介绍1.2flask介绍1.3wsgiref1.4用wsgirf和werkzeug写web二、flask快速使用三、登录,显示用户信息小案例3.1login.html3.2home.html3.3detail.html3.4py文件3.5知识点总结四、配置文件的使用方式1、设置方式一(测试中使用的......
  • 蓝图与数据连接池
    蓝图的使用#blueprint翻译过来的,称之为蓝图#作用是:之前全在一个py文件中写flask,后期肯定要划分目录不用蓝图划分目录 no_blueprint_flask#项目名src#核心源码位置__init__.py#包里面实例化得到了app对象,models.p......
  • flask数据库连接
    flask数据库连接flask连接数据库flask连接数据库需要借助pymysql模块,相当于一个mysql的客户端连接。那么问题来了,我们应该按照什么策略去连接数据库?来一个请求连一次,请求处理完后断开数据库连接当并发量过高时,会有数据库服务端无法处理的隐患且每次请求都重新连接数据库一......
  • flask框架03 蓝图的使用 g对象 数据库连接池
    今日内容目录今日内容1蓝图的使用2g对象3数据库连接池1蓝图的使用#blueprint翻译过来的,称之为蓝图#作用是:之前全在一个py中写flask项目,后期肯定要划分目录#不用蓝图,划分目录 no_blueprint_flask#项目名src#核心源码位置__i......
  • flask3
    1蓝图的使用#blueprint翻译过来称之为蓝图#作用是:之前全在一个py中写flask项目,后期肯定要划分目录#不用蓝图,划分目录 no_blueprint_flask#项目名src#核心源码位置__init__.py#包里面实例化得到了app对象,models.......
  • flask项目结构参考与g对象
    flask项目结构参考与g对象flask本身是一个轻量化的框架,如果选择flask做项目,大部分时候,可能并不是打算运行特别庞大的项目,因此flask项目的结构并没有特别统一的规范,这篇文章仅作参考。flask蓝图蓝图——blueprint蓝图的基本使用fromflaskimportFlask,Blueprintapp=Fla......
  • 1 蓝图的使用 、2 g对象 、3 数据库连接池
    目录1蓝图的使用2g对象3数据库连接池1蓝图的使用#blueprint翻译过来的,称之为蓝图#作用是:之前全在一个py中写flask项目,后期肯定要划分目录#不用蓝图,划分目录 no_blueprint_flask#项目名src#核心源码位置__init__.py#包里......
  • Flask 框架
    Flask和pythonweb框架介绍#pythonweb框架,本质其实都是一样的--django:大而全,它自身自带着很多的内置app,提供了很多的方法,第三方的app也很多--flask:小而精,没有过多的内置组件,只能完成web框架最基本的功能,需要借助于第三方,完成更加丰富的功能--web:是一个小巧的python框......
  • flask,mysql实现用户登录注册注销改密
    flask.py文件fromflaskimportFlask,render_template,request,redirect,url_for,flash,sessionfromflask_mysqldbimportMySQLimportbcryptapp=Flask(__name__)app.secret_key="secret"#MySQLconfigurationsapp.config['MYSQL_HOST'......
  • day35 860. 柠檬水找零
    在柠檬水摊上,每一杯柠檬水的售价为 5 美元。顾客排队购买你的产品,(按账单bills支付的顺序)一次购买一杯。每位顾客只买一杯柠檬水,然后向你付5美元、10美元或20美元。你必须给每个顾客正确找零,也就是说净交易是每位顾客向你支付5美元。注意,一开始你手头没有任何零钱。......