当前位置:网站首页>Flask framework in-depth two
Flask framework in-depth two
2022-08-02 14:21:00 【Spaghetti Mixed with No. 42 Concrete】
FlaskThe framework goes deep into two
一、flask-session
# 原生的sessionThe data is encrypted and placedcookie中
# 以后可以把session放在数据库中,redis,文件中....
# pip install flask-session
# 方式一
from flask import Flask,session
from flask_session import RedisSessionInterface
import redis
app = Flask(__name__)
app.config['DEBUG'] = True
conn = redis.Redis()
app.session_interface = RedisSessionInterface(conn,key_prefix='zz')
@app.route('/')
def index():
session['name'] = 'zhangzhang'
return 'hello flask!'
if __name__ == '__main__':
app.run()
# 方式二:(通用方案:flaskIntegrate third-party common solutions)
from flask_session import Session
# 配置文件
app.config['SESSION_TYPE'] = 'redis'
app.config['SESSION_KEY_PREFIX'] = 'lqz'
app.config['SESSION_REDIS'] = redis.Redis()
Session(app) # 源码在这---》Inside is done app.session_interface=RedisSessionInterface(app.config['SESSION_REDIS'])
@app.route('/')
def index():
session['name'] = 'lqz'
return 'hello'
if __name__ == '__main__':
app.run()
二、数据库连接池
# Why have a database connection pool
-With the increasing amount of concurrency,mysqlThe number of connections will also increase---》After we create the connection pool,Used every time a connection is obtained from the pool,Can avoid excessive concurrency,The danger of database collapse
# pip install dbutils
# 创建池对象
from flask import Flask, session
from dbutils.pooled_db import PooledDB
import pymysql
app = Flask(__name__)
app.config['DEBUG'] = True
POOL = PooledDB(
creator=pymysql, # 使用链接数据库的模块
maxconnections=6, # 连接池允许的最大连接数,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='786017877', # 数据库密码
database='knowgood',# 数据库名称
charset='utf8' # 数据库编码
)
@app.route('/')
def index():
# Take the link from the pool
conn = POOL.connection()
cursor = conn.cursor()
cursor.execute('select * from applet_user')
print(cursor.fetchall())
return 'hello flask!'
if __name__ == '__main__':
app.run()
# 了解
-django和flaskBoth are synchronous frameworks
-来一个请求,Start the thread to execute the view function
-异步框架:sanic,fastapi,只要被async装饰的函数,is the coroutine function
@app.route("/")
async def test(request):
await cousor.excute()
return json({
"hello": "world"})
# 协程:单线程下实现并发
# 一旦用了异步,All frameworks must use async
-pymysql,redis是同步框架
-Cannot be used in asyncweb框架中
-Requires the use of specialized async modules
-aiomysql,aioredis,python到目前为止,There isn't a better asyncorm框架
-django 3.0以后支持异步
-但是django的orm不支持异步
-python的orm框架
-django的orm:同步
-sqlalchemy:同步
-peewee:同步和异步
# aioredis和aiomysql的使用
# Why once use an asynchronous framework,All use asynchronous
三、wtfroms(了解)
# 等同于django的forms,表单验证,模板渲染,Suitable for projects with mixed front-end and back-end
1、登录案例
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
app = Flask(__name__)
app.debug = True
# 写了个form类
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)(?=.*[[email protected]$!%*?&])[A-Za-z\[email protected]$!%*?&]{8,}",
message='密码至少8个字符,至少1个大写字母,1个小写字母,1个数字和1个特殊字符')
],
widget=widgets.PasswordInput(),
render_kw={
'class': 'form-control'}
)
@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)
if __name__ == '__main__':
app.run()
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>登录</h1>
<form method="post">
<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>
2、注册案例
from flask import Flask, render_template, request, redirect
from wtforms import Form
from wtforms.fields import core
from wtforms.fields import html5
from wtforms.fields import simple
from wtforms import validators
from wtforms import widgets
app = Flask(__name__, template_folder='templates')
app.debug = True
class RegisterForm(Form):
name = simple.StringField(
label='用户名',
validators=[
validators.DataRequired()
],
widget=widgets.TextInput(),
render_kw={
'class': 'form-control'},
default='egon'
)
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 = html5.EmailField(
label='邮箱',
validators=[
validators.DataRequired(message='邮箱不能为空.'),
validators.Email(message='邮箱格式错误')
],
widget=widgets.TextInput(input_type='email'),
render_kw={
'class': 'form-control'}
)
gender = core.RadioField(
label='性别',
choices=(
(1, '男'),
(2, '女'),
),
coerce=int # “1” “2”
)
city = core.SelectField(
label='城市',
choices=(
('bj', '北京'),
('sh', '上海'),
)
)
hobby = core.SelectMultipleField(
label='爱好',
choices=(
(1, '篮球'),
(2, '足球'),
),
coerce=int
)
favor = core.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('/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()
<!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>
四、信号(重要)
1、Flask信号
Flask框架中的信号基于blinker,其主要就是让开发者可是在flask请求过程中定制一些用户行为(Such as operation records are written to the log,或者写入数据库)
# Multi-threaded concurrency safety issues:Multiple threads operate on the same data at the same time,出现错乱
# 使用同步锁--》Get it before modifying the data---》开始修改---》释放锁--》someone else will take it
# 线程锁----》分布式锁
# 悲观锁和乐观锁
# 同步锁(互斥锁),递归锁(可重入锁),Event事件,Semaphore(信号量)多把锁
# 安装:pip3 install blinker
内置信号
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') # 请求执行完毕后自动执行(无论成功与否)
appcontext_tearing_down = _signals.signal('appcontext-tearing-down')# 应用上下文执行完毕后自动执行(无论成功与否)
appcontext_pushed = _signals.signal('appcontext-pushed') # 应用上下文push时执行
appcontext_popped = _signals.signal('appcontext-popped') # 应用上下文pop时执行
message_flashed = _signals.signal('message-flashed') # 调用flask在其中添加数据时,自动触发
# 自定义信号(我们自定义的)
# 内置信号使用
# The built-in signal performs the usage steps:
# The signal executes after the template is rendered
# 功能:home页面被渲染,记录一条日志
# 第一步:写一个函数
def template_test(*args,**kwargs):
print(args)
print(kwargs)
print('The template is rendered')
# 第二步:Bind to the built-in signal:template_rendered
template_rendered.connect(template_test)
# 第三不:Trigger signal execution(We don't need to do it)
### 自定义信号的使用
###### Custom signal steps
# 第0步:自定义一个信号
xxxxx = _signals.signal('xxxxx')
# 第一步:写一个函数
def xxx_test(*args, **kwargs):
print(args)
print(kwargs)
print('xxxThe signal is triggered')
# 第二步:Bind the custom signal signal:xxxxx
xxxxx.connect(xxx_test)
# 第三步:Trigger signal execution(手动触发,trigger at a certain location,For example, in the view function)
@app.route('/')
def index():
xxxxx.send() # 触发信号
return 'hello'
2、Django信号
# 内置信号
Model signals
pre_init # django的modal执行其构造方法前,自动触发
post_init # django的modal执行其构造方法后,自动触发
pre_save # django的modal对象保存前,自动触发
post_save # django的modal对象保存后,自动触发
pre_delete # django的modal对象删除前,自动触发
post_delete # django的modal对象删除后,自动触发
m2m_changed # django的modal中使用m2m字段操作第三张表(add,remove,clear)前后,自动触发
class_prepared # 程序启动时,检测已注册的app中modal类,对于每一个类,自动触发
Management signals
pre_migrate # 执行migrate命令前,自动触发
post_migrate # 执行migrate命令后,自动触发
Request/response signals
request_started # 请求到来前,自动触发
request_finished # 请求结束后,自动触发
got_request_exception # 请求异常后,自动触发
Test signals
setting_changed # 使用test测试修改配置文件时,自动触发
template_rendered # 使用test测试渲染模板时,自动触发
Database Wrappers
connection_created # 创建数据库连接时,自动触发
#放到__init__里
from django.db.models.signals import pre_save
import logging
def callBack(sender, **kwargs):
print(sender)
print(kwargs)
# 创建对象写日志
logging.basicConfig(level=logging.DEBUG)
# logging.error('%s创建了一个%s对象'%(sender._meta.db_table,kwargs.get('instance').title))
logging.debug('%s创建了一个%s对象'%(sender._meta.model_name,kwargs.get('instance').title))
pre_save.connect(callBack)
五、flask-script
1、启动命令
# Implement a command like this:python manage.py runserver
# 自定义命令:
# django 自定义命令
python manage.py initdb xx.xsl article #Just execute this command,to the databasearticle表中写入xx.xsl的数据
# pip3 install flask-script
####基本使用
from flask import Flask
app = Flask(__name__)
# 第一步导入
from flask_script import Manager
# The second step is packaging
manager = Manager(app)
@app.route('/')
def index():
return 'hello'
if __name__ == '__main__':
# app.run()
# 第三步使用
manager.run()
2、自定义命令
######### 自定义命令
@manager.command
def custom(arg):
""" 自定义命令 python manage.py custom 123 :param arg: :return: """
print(arg)
@manager.option('-n', '--name', dest='name')
@manager.option('-u', '--url', dest='url')
def cmd(name, url):
""" 自定义命令(-n也可以写成--name) 执行: python manage.py cmd -n lqz -u http://www.oldboyedu.com 执行: python manage.py cmd --name lqz --url http://www.oldboyedu.com :param name: :param url: :return: """
print(name, url)
边栏推荐
- Building and getting started with the Flask framework
- Linux:CentOS 7 安装MySQL5.7
- drf serializer - Serializer
- 【ROS】工控机的软件包不编译
- The world's largest Apache open source foundation is how it works?
- [ROS] (04) Detailed explanation of package.xml
- You can't accept 60% slump, there is no eligible for gain of 6000% in 2021-05-27
- Steps to connect the virtual machine with xshell_establish a network connection between the host and the vm virtual machine
- 8580 合并链表
- Flask framework in-depth
猜你喜欢
[ROS] Introduction to common tools in ROS (to be continued)
第八单元 中间件
Interview | with questions to learn, Apache DolphinScheduler Wang Fuzheng
logback源码阅读(一)获取ILoggerFactory、Logger
The world's largest Apache open source foundation is how it works?
Sentinel源码(六)ParamFlowSlot热点参数限流
What are the file encryption software?Keep your files safe
第十一单元 序列化器
Unit 11 Serializers
Network pruning (1)
随机推荐
Flask框架的搭建及入门
Sentinel源码(六)ParamFlowSlot热点参数限流
跑yolov5又出啥问题了(1)p,r,map全部为0
深度学习框架pytorch快速开发与实战chapter3
【VCU】详解S19文件(S-record)
[ROS] The difference between roscd and cd
Sentinel源码(二)入口方法分析
瑞吉外卖笔记——第08讲读写分离
Mysql's case the when you how to use
【Tensorflow】AttributeError: module 'keras.backend' has no attribute 'tf'
Steps to connect the virtual machine with xshell_establish a network connection between the host and the vm virtual machine
Unit 8 Middleware
如何自定义feign方法级别的超时时间
How to solve 1045 cannot log in to mysql server
xshell连接虚拟机步骤_建立主机与vm虚拟机的网络连接
LayoutParams的详解
drf视图组件
Interview | with questions to learn, Apache DolphinScheduler Wang Fuzheng
The 2nd China Rust Developers Conference (RustChinaConf 2021~2022) Online Conference Officially Opens Registration
logback源码阅读(二)日志打印,自定义appender,encoder,pattern,converter