flask之g对象、flask-session使用、数据库连接池、信号

news2024/11/25 2:37:34

目录

g对象

flask-session的使用

数据库连接池

flask中集成mysql

wtfroms使用(了解)

信号


g对象

全称global,是一个全局对象在此次请求过程中一直有效,其实就是请求的上下文从请求进来就一直存在直到请求结束,所以在当次请求过程中,如果调用别的函数不需要把参数传入只需要放到g对象中在别的函数中直接使用g获取即可

具体使用

user.py

from flask import Flask, g
from home import text

app = Flask(__name__)

app.debug = True


@app.route('/')
def index():
	# 给g对象放入值
    g.username = 'abc'
    text()
    return 'ok'


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

home.py

from flask import g


def text():
	# 请求可以使用g对象中的值
    print(f'用户:{g.username}')

ps:g对象和session的区别

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

flask-session的使用

flask内置的session把数据加密后保存到浏览器中,那我们能不能自己写session类来重写open_session和save_session把数据保存到服务端到redis中,而flask-session就是用来干这个事,可以把数据保存到redis、mongodb等

安装

pip3 install flask-session # 安装
pip3 install -U flask-session # 升级最新

快速使用

from flask import Flask, session
from flask_session.sessions import RedisSessionInterface
from redis import Redis

app = Flask(__name__)
# conn = Redis(host='localhost', port=6379, db=2)
# app.session_interface = RedisSessionInterface(redis=conn, key_prefix='flask-')
app.session_interface = RedisSessionInterface(redis=None, key_prefix='flask-')
app.debug = True


@app.route('/')
def index():
    session['name'] = 'abc'
    return 'index'


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

通用方案(常用流程):

from flask import Flask, session
from flask_session import Session

app = Flask(__name__)

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

Session(app) 
# 导入一个类把app传入,本质就是根据配置文件,生成 RedisSessionInterface 对象,赋值给app.session_interface


@app.route('/')
def index():
    session['username'] = 'abc'
    return 'index'


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

settings.py

from redis import Redis

DEBUG = True
SESSION_TYPE = 'redis'
SESSION_REDIS = Redis(db=2)
SESSION_KEY_PREFIX = 'flask-'

在配置文件中给session配置过期时间

import datetime

PERMANENT_SESSION_LIFETIME = datetime.timedelta(seconds=10)# seconds:秒,days:天

设置cookie使浏览器关闭就失效

# expires 设置为None,就是浏览器关闭cookie就失效了

res = make_response('hello')
res.set_cookie('name','abc',expires=None)

# session设置的cookie,关闭浏览器失效
方式一:
app.session_interface =RedisSessionInterface(redis=conn,key_prefix='abc',permanent=False)

方式二:在配置文件中改
SESSION_PERMANENT=False

数据库连接池

flask中集成mysql

from flask import Flask, jsonify
import pymysql

app = Flask(__name__)

app.debug = True


@app.route('/show')
def show_article():
    conn = pymysql.connect(user='root', password='123', host='localhost', port=3306, database='message')
    cursor = conn.cursor()
    cursor.execute('select * from user')
    res = cursor.fetchall()
    cursor.close()
    conn.close()
    print(res)
    return jsonify(res)


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

直接使用上面的代码链接数据库会存在问题,每当请求过来后都会打开mysql链接进行操作,操作完关闭链接,如果并发量很高的时候mysql就会支撑不住并发,所以我们需要用到数据库池来进行控制

安装第三方:DBUtils

pip install DBUtils

快速使用:text.py

from dbutils.pooled_db import PooledDB
import pymysql
# 在py中实例化一个池
POOL = PooledDB(
    creator=pymysql,    #使用链接数据库的模块
    maxconnections=6,   #连接池允许的最大链接数,0和None表示不限制
    mincached=2,        #初始化时,链接池中至少创建的空闲的链接
    maxcached=5,        #链接池中最多闲置的链接,0和None不限制
    maxshared=0,      # 链接池中最多共享的链接数量,0和None表示全部共享。
# PS: 无用,因为pymysql和MySQLdb等模块的 threadsafety都为1,所有值无论设置为多少,_maxcached永远为0,所以永远是所有链接都共享。
    blocking=True,    # 连接池中如果没有可用连接后,是否阻塞等待。True,等待;False,不等待报错
    maxusage=None,    # 一个链接最多被重复使用的次数,None表示无限制
    setsession=[],  # 可选的用于准备的SQL命令列表
    reset=True,  # 当连接返回到池时应该如何重置(False或None回滚以begin()开始的事务,为了安全起见,总是发出回滚)
    failures=None,  # 对于需要应用连接故障转移机制的
    ping=0,  # 用ping()确定何时检查连接。(0 = None = never, 1 = default =无论何时从池中获取,2 =创建游标时,4 =执行查询时,7 =总是,以及这些值的所有其他位组合)
    host='localhost',
    port=3306,
    user='root',
    password='123',
    database='message',
    charset='utf8'
)

在视图中使用

from flask import Flask, jsonify
fromt text import POOL

app = Flask(__name__)

app.debug = True


@app.route('/show')
def show_article():
	# 连接池中取一个链接
    conn = POOL.connection()
    cursor = conn.cursor()
    cursor.execute('select * from user')
    res = cursor.fetchall()
    return jsonify(res)


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

链接mysql查看当前连接数:

show status like 'Threads%'

总结:当使用了链接池后,无论客户端链接数有多大,mysql的连接数最多就是自己在实例化池的时候指定的数量

wtfroms使用(了解)

和django中学的forms组件是一个东西,用来校验数据、渲染错误信息、渲染页面

python代码

from flask import Flask, render_template, request, redirect

from wtforms import Form
from wtforms.fields import simple
from wtforms import validators
from wtforms import widgets
from wtforms.fields import choices
app = Flask(__name__, template_folder='templates')

app.debug = True


class LoginForm(Form):
    # 字段(内部包含正则表达式)
    name = simple.StringField(
        label='用户名',
        validators=[
            validators.DataRequired(message='用户名不能为空.'),
            validators.Length(min=6, max=18, message='用户名长度必须大于%(min)d且小于%(max)d')
        ],
        widget=widgets.TextInput(),  # 页面上显示的插件
        render_kw={'class': 'form-control'}

    )
    # 字段(内部包含正则表达式)
    pwd = simple.PasswordField(
        label='密码',
        validators=[
            validators.DataRequired(message='密码不能为空.'),
            validators.Length(min=8, message='用户名长度必须大于%(min)d'),
            validators.Regexp(regex="^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[$@$!%*?&])[A-Za-z\d$@$!%*?&]{8,}",
                              message='密码至少8个字符,至少1个大写字母,1个小写字母,1个数字和1个特殊字符')

        ],
        widget=widgets.PasswordInput(),
        render_kw={'class': 'form-control'}
    )


class RegisterForm(Form):
    name = simple.StringField(
        label='用户名',
        validators=[
            validators.DataRequired()
        ],
        widget=widgets.TextInput(),
        render_kw={'class': 'form-control'},
        default='pyy'
    )

    pwd = simple.PasswordField(
        label='密码',
        validators=[
            validators.DataRequired(message='密码不能为空.')
        ],
        widget=widgets.PasswordInput(),
        render_kw={'class': 'form-control'}
    )

    pwd_confirm = simple.PasswordField(
        label='重复密码',
        validators=[
            validators.DataRequired(message='重复密码不能为空.'),
            validators.EqualTo('pwd', message="两次密码输入不一致")
        ],
        widget=widgets.PasswordInput(),
        render_kw={'class': 'form-control'}
    )

    email = simple.EmailField(
        label='邮箱',
        validators=[
            validators.DataRequired(message='邮箱不能为空.'),
            validators.Email(message='邮箱格式错误')
        ],
        widget=widgets.TextInput(input_type='email'),
        render_kw={'class': 'form-control'}
    )

    gender = choices.RadioField(
        label='性别',
        choices=(
            (1, '男'),
            (2, '女'),
        ),
        coerce=int # “1” “2”
     )
    city = choices.SelectField(
        label='城市',
        choices=(
            ('bj', '北京'),
            ('sh', '上海'),
        )
    )

    hobby = choices.SelectMultipleField(
        label='爱好',
        choices=(
            (1, '篮球'),
            (2, '足球'),
        ),
        coerce=int
    )

    favor = choices.SelectMultipleField(
        label='喜好',
        choices=(
            (1, '篮球'),
            (2, '足球'),
        ),
        widget=widgets.ListWidget(prefix_label=False),
        option_widget=widgets.CheckboxInput(),
        coerce=int,
        default=[1, 2]
    )

    def __init__(self, *args, **kwargs):
        super(RegisterForm, self).__init__(*args, **kwargs)
        self.favor.choices = ((1, '篮球'), (2, '足球'), (3, '羽毛球'))

    def validate_pwd_confirm(self, field):
        """
        自定义pwd_confirm字段规则,例:与pwd字段是否一致
        :param field:
        :return:
        """
        # 最开始初始化时,self.data中已经有所有的值

        if field.data != self.data['pwd']:
            # raise validators.ValidationError("密码不一致") # 继续后续验证
            raise validators.StopValidation("密码不一致")  # 不再继续后续验证

@app.route('/login', methods=['GET', 'POST'])
def login():
    if request.method == 'GET':
        form = LoginForm()
        return render_template('login.html', form=form)
    else:
        form = LoginForm(formdata=request.form)
        if form.validate():
            print('用户提交数据通过格式验证,提交的值为:', form.data)
        else:
            print(form.errors)
        return render_template('login.html', form=form)


@app.route('/register', methods=['GET', 'POST'])
def register():
    if request.method == 'GET':
        form = RegisterForm(data={'gender': 2, 'hobby': [1, ]})  # initial
        return render_template('register.html', form=form)
    else:
        form = RegisterForm(formdata=request.form)
        if form.validate():
            print('用户提交数据通过格式验证,提交的值为:', form.data)
        else:
            print(form.errors)
        return render_template('register.html', form=form)


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

html代码:注册页面

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>用户注册</h1>
<form method="post" novalidate style="padding:0  50px">
    {% for field in form %}
    <p>{{field.label}}: {{field}} {{field.errors[0] }}</p>
    {% endfor %}
    <input type="submit" value="提交">
</form>
</body>
</html>

html代码:登陆页面

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>登录</h1>
<form method="post" novalidate>
    <p>{{form.name.label}} {{form.name}} {{form.name.errors[0] }}</p>

    <p>{{form.pwd.label}} {{form.pwd}} {{form.pwd.errors[0] }}</p>
    <input type="submit" value="提交">
</form>
</body>
</html>

信号

\bullet 信号:signal:Flask框架中的信号基于blinker,其主要就是让开发者可是在flask请求过程中定制一些用户行为

\bullet 信号量:Semaphore:信号量可以理解为多把锁,同时允许多个线程来更改数据

flask内置信号

# 请求到来前执行
request_started = _signals.signal('request-started')

# 请求结束后执行
request_finished = _signals.signal('request-finished')

# 模板渲染前执行
before_render_template = _signals.signal('before-render-template')

# 模板渲染后执行
template_rendered = _signals.signal('template-rendered')

# 请求执行出现异常时执行
got_request_exception = _signals.signal('got-request-exception') 

# 请求执行完毕后自动执行(无论成功与否)
request_tearing_down = _signals.signal('request-tearing-down')

# 调用flashed在其中添加数据时,自动触发
message_flashed = _signals.signal('message-flashed')

内置信号使用:

1.定义函数

2.跟内置信号绑定

3.等待信号被触发

from flask import Flask, render_template, signals

app = Flask(__name__)


def before_render(*args, **kwargs):
    print(args)
    print(kwargs)
    print('模板渲染前执行')


def rendered(*args, **kwargs):
    print(args)
    print(kwargs)
    print('模板渲染后执行')


signals.before_render_template.connect(before_render)
signals.template_rendered.connect(rendered)


@app.route('/index')
def index():
    return render_template('index.html')


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

自定义信号使用步骤:

1.定义一个自定义信号

2.定义一个函数

3.函数跟自定义信号绑定

4.某种情况下触发执行

# 定义信号
name = _signals.signal('abc')

# 定义函数
def test(*args, **kwargs):
    print(args)
    print(kwargs)
    print('我执行了')

# 绑定自定义的信号
defined.connect(test)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/89395.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

华为云WeLink云空间,企业的多啦A梦「百宝袋」办公助手

我们知道&#xff0c;源自华为19万员工的数字化办公实践的华为云WeLink&#xff0c;作为新一代智能工作平台、远程办公平台、移动办公平台、协同办公软件&#xff0c;已经给成为企业数字化转型的连接器。今天&#xff0c;我们来聊一聊WeLink提供的一项优质服务——云空间。 We…

论文复现-2代码研读:Black-Box Tuning for Language-Model-as-a-Service

第一步&#xff1a;将作者所给代码跑通。 下载代码&#xff0c;放置在本地文件夹。 报错问题一&#xff1a; 使用hugging face 中loaddataset函数报错。显示connect error。 修改如下&#xff1a;将数据集下载文件.py文件在本地&#xff0c;然后从.py文件中加载数据集。 解决…

【深度学习】PyTorch深度学习实践 - Lecture_13_RNN_Classifier

文章目录一、问题描述二、OurModel三、准备数据3.1 Data Convert3.2 Padding Data3.3 Label Convert四、双向RNN五、PyTorch代码实现5.1 引入相关库5.2 创建Tensors函数5.3 将名字转化为字符列表函数5.4 国家名字数据集对象5.5 RNN&#xff08;GRU&#xff09;分类器对象5.6 训…

Nacos--多环境的实现方案

原文网址&#xff1a;Nacos--多环境的实现方案_IT利刃出鞘的博客-CSDN博客 简介 说明 本文介绍Nacos实现多环境的方案。 方案概述 多环境有很多方案&#xff0c;如下&#xff1a; 单租户方案&#xff08;适用于项目很少的场景&#xff09; 命名空间区分环境&#xff0c;GR…

Python简介

Python简介 目录1. 概述2. 安装3. 编译器4. 注释5. 缩进6. 编码规范7. 基本输入输出使用print()函数输出使用input()函数输入8. 练习1. 概述 Python的中文意思是蟒蛇&#xff0c;python是一种面向对象的解释型的计算机程序设计语言。支持面向过程&#xff0c;面向对象&#xff…

(十四)Vue之收集表单数据

文章目录v-model的三个修饰符收集文本框收集单选按钮收集复选框收集下拉列表收集文本域演示程序Vue学习目录 上一篇&#xff1a;&#xff08;十三&#xff09;Vue之监测数据改变的原理 v-model的三个修饰符 v-model的三个修饰符&#xff1a; lazy&#xff1a;失去焦点再收集…

MIT6.830-2022-lab2实验思路详细讲解

目录一、Exercise1.1、Exercise1&#xff1a; Filter and Join1.2、Exercise2&#xff1a; Aggregates1.3、Exercise 3&#xff1a;HeapFile Mutability1.4、Exercise 4&#xff1a;Insertion and deletion1.5、Exercise 5&#xff1a; Page eviction二、总结一、Exercise 1.1…

人工智能课后作业_python实现A*算法实现8数码问题(附源码)

3 A*算法实现8数码问题 3.1算法介绍3.2实验代码3.3实验结果3.4实验总结 3.1算法介绍 Astar算法是一种求解最短路径最有效的直接搜索方法&#xff0c;也是许多其他问题的常用启发式算法。它的启发函数为f(n)g(n)h(n),其中&#xff0c;f(n) 是从初始状态经由状态n到目标状态的…

竞拍拍卖管理系统

开发工具(eclipse/idea/vscode等)&#xff1a; 数据库(sqlite/mysql/sqlserver等)&#xff1a; 功能模块(请用文字描述&#xff0c;至少200字)&#xff1a; 网站前台&#xff1a;关于我们、联系我门、公告信息、拍卖物品&#xff0c;拍卖完成 管理员功影&#xff1a; 1、管理关…

信贷反欺诈体系介绍及其策略规则应用

在信贷业务的风控体系中&#xff0c;反欺诈始终是一个重要话题&#xff0c;与信用评估构成的贷前风控两大模块&#xff0c;对于贷前风险的防范控制发挥着决定性作用。反欺诈虽然在理解层面上感觉略显简单&#xff0c;但由于场景的复杂性与丰富度&#xff0c;使得反欺诈在研究开…

PD QC快充诱骗取电方案:输出9V12V15V20V

手机快充充电器或充电宝&#xff0c;在没有与手机通讯时&#xff0c;快充充电器相当于普通的充电器只输出5V电压&#xff0c;要想得到充电器的9V/12V等电压&#xff0c;可以使用快充取电电路。 或者也可以使用电子元件来搭建诱骗电路&#xff0c;但是和专用的取电芯片方案相比&…

Part 1:RPA的发展历程

Robot一词的来源 捷克科幻小说家卡雷尔恰佩克创作&#xff0c;于1921 年在布拉格首映的《罗素姆万能机器人》作品中首次出现“robot”&#xff08;机器人&#xff09;一词。这个词源于捷克语的“robota”&#xff0c;意思是“苦力”。恰佩克的机器人原本是为它们的人类主人服务…

Python使用Selenium Webdriver爬取网页所有内容

Python使用Selenium Webdriver爬取网页所有内容一、为什么我抓不到网页的全部html内容二、Selenium的基本使用三、使用Selenium抓取全部HTML一、为什么我抓不到网页的全部html内容 有时候&#xff0c;我们在用urllib或者requests库抓取页面时&#xff0c;得到的html源代码和浏…

4年测试在岗,薪资却被春招来的年轻人超过了,其实你一直在假装努力~

最近和一位同行朋友聊天&#xff0c;一开始大家也没有谈工作&#xff0c;毕竟是出来聚聚&#xff0c;放松一下&#xff0c;吃饭的时候&#xff0c;喝了点小酒&#xff0c;酒过三巡&#xff0c;这个朋友开始诉苦水&#xff0c;大概意思嘞&#xff0c;我给大家概况一下&#xff0…

STM32F4的关键要点分析

1. 从以上截图信息可以看出&#xff1a; 1.当外设数据宽度和内存数据宽度不相等时&#xff0c;要传输的数据项数目的数据宽度由外设数据宽度确定&#xff1b; 2.在直接模式下&#xff08;不使用FIFO&#xff09;&#xff0c;不能进行数据的封装/解封&#xff0c;且源数据宽度和…

Docker-Docker安装nginx

目录 一&#xff0c;容器之间的相互通信 ping 1.1 两个容器在同一网段 1.2 两个容器在不同网段 二&#xff0c;安装Nginx 2.1 nginx是什么 安装步骤 2.4 部署前端项目 上传项目 步骤 一&#xff0c;容器之间的相互通信 ping 1.1 两个容器在同一网段 1.2 两个容器在不同网段…

旋转机械 | 基于ANSYS WB平台的滑动轴承分析工具(一)

导读&#xff1a;本文主要针对Tribo-X inside ANSYS的功能及各方向应用实例进行介绍&#xff0c;限于篇幅关系会分五篇进行介绍&#xff0c;第一篇主要结合软件的需求、理论、功能及应用方向进行介绍&#xff0c;第二篇至第五篇将结合具体应用方向的示例进行介绍。本篇为第一篇…

软件测试工程师的简历项目经验该怎么写?

想要找一份高薪的软件测试工作&#xff0c;简历项目必不可少&#xff08;即使是应届生&#xff0c;你也要写上实习项目&#xff09;。所以很多自学的朋友找工作时会碰到一个令人颇感绝望的拦路虎&#xff1a;个人并没有实际的项目工作经验怎么办&#xff1f; 怎么办&#xff1…

【PS】画笔工具

目录 画直线 拾取颜色 改变画笔大小 改变画笔硬度 不透明度 流量 画笔预设 自定义图片做笔刷 工具预设 画笔面板 画直线 Shift键可画出直线只用点两个点就画出直线&#xff1a;先点一个点&#xff0c;按住shift&#xff0c;再在别处点一点&#xff0c;这时候直线就形…

Python 中如何使用pybind11调用C++

Python 中如何使用pybind11调用C1. pybind11简介与环境安装2. 求和函数3. STL和python内建数据类型的对应关系3.1 **返回vector**3.2 **返回struct**4. pybind11与numpy图像数据接口和速度对比&#xff1a;以图像rgb转化为gray的例子Reference: 混合编程&#xff1a;如何用pyb…