一.flask 之路由
url_for 方向解析路由
1.一个装饰器
@app.route('/') 1.end point 没有指定时默认为 函数的名 endpoint='index' 就反向解析到路由 'index'----> '/'
def index(): 2.指定 endpoint = 'wyc' 'wyc' ------> '/'
return '123'
2.两个装饰器
def wrpaer(fn):
def inner(*args,**kwargs):
ret=fn(*args,**kwargs)
return ret
return inner
@app.route('/') @app.route('/detail')
@wrpaer @wrpaer
def index(): def detail():
return '123' return '123'
装饰器: wrpaer(index) --->inner 所以现在两个 视图函数的名字就是inner 而默认endpoint 使用函数名反向解析 'inner'
'inner' ---->'/' 'inner' ---> 'detail' 就会报错 所以使用endpoint='' 指定一个不同的字符串 就可以解决问题
3.视图函数的几个参数
method=[] endpoint='' strict_slashes是否严格遵循路由地址 默认为True redirect_to='' 重定向 视图函数就不执行了
defaults={'a':1} 给函数传一个默认值 视图函数必须接受这个值
4.动态路由
app.route('/<id>/<int:num>/<string: str>') 默认string 视图函数必须接受这个参数 id num ,string
5.flask 实例化配置 参数
template_folder='templates', 模板存放地址,网页
static_folder='statics', 静态文件目录地址 默认是 static
static_url_path='/statics' 静态文件访问地址 前面必须加一个 /
static_host='www.baidu.com' 把 自己的域名更换
6.flask 对象配置
1. 直接app.来配置 app.secret_key=' ' 使用session 配置
app.session_cookie_name='' cookie 的名字 app.debug=True
2. 使用文件配置 新建一个setting 文件 app.config.from_object(setting.Test) --> 可以随意切换
class Test():
SECRET_KEY='TEST'
SESSION_COOKIE_NAME='test'
DEBUG=True
class Debug():
SECRET_KEY='TEST'
SESSION_COOKIE_NAME='test'
7.蓝图
1.新建一个app01的包 新建user.py 文件
from flask import Blueprint,render_template
user_blue=Blueprint('user',__name__,url_prefix='/user',template_folder='user_temp')
@user_blue.route('user_add')
def user_add():
return render_template('user_add.html')
ur_prefix 的意思 就是 蓝图下面的 视图 url 前都加上一个/user 才能访问 ,其他用法 与flask 一样
2. 1.导入:from app01 import user 2.注册 : app.register_blueprint(user.user_blue)
8.flash 闪存
from flask import flash,get_flash_messages
flash("ddd","tag")
get_flash_messages(["tag"])
二.特殊装饰器 相当于中间件
@app.before_request 进入视图函数之前
def is_login():
if request.path == '/login':
if session.get('user'):
return None 跳过
else:
return '缺失session'
return None
这样就可以 让没有session 的用户 无法登录 return None 的意思就是继续执行 放行 如果return 了
resposne 后面的视图就不执行了
@app.after_request 视图结束之后,返回浏览器之前,如果有多个 每一个按倒序执行
def affter(res): 如果before_request 有一个出现异常 每一个按倒序执行
return res
任何返回给 浏览器响应之前都 执行 affter 函数 和django不一样的是request和resposne 不一一对应
before_request返回resposne 时 执行每一个 affter_request 和写的循序倒序执行
3.@app.errorhandler(404) 处理指定的异常
@app.errorhandler(404)
def error(arg): arg是原始错误信息
return '页面不存在'
4.@app.template_global() 全局函数 每个模板都能使用 5. @app.template_filter() 偏函数
三.flask 之 CBV
from flask import views
class LoginView(views.MethodView):
def get(self): #method=['GET','POST'] 写了什么才执行
return
def post(self):
return
app.add_url_rule("/login",endpoint=None,view_func=LoginView.as_view(name="login"))
as_view() 必须传一个参数 可以随意取
四. flask 之 第三方
1.session
from flask_session import Session pip install flask_session
from flask import session 原始session 还是得导入
app.config['SESSION_TYPE']= ' redis ' 配置使用 redis 来存储 加密session
app.config[' SESSION_REDIS'] = Redis('127.0.0.1' ,6379, db= 1 ) 配置连接redis 的第几个数据库 一共0-15
SESSION(app) 重新设置app
@app.route('/login')
def login():
session['user']='WYC' 这里的session 就不需要普通的session_key了 这里的是存储在redis
return 'login' 经过加密的session
2.wtforms
1. form 表单写法
from flask import Flask,request,render_template,views
from wtforms.fields import simple,core
from wtforms import Form
from wtforms import validators
class LoginForm(Form):
username=simple.StringField( 普通的都是simple 里面的
label='用户名',
validators=[
validators.DataRequired(message='不能为空'),
validators.Email(message='格式不正确'),
]
)
password=simple.PasswordField(
label='密码',
validators=[
validators.Length(min=3,max=10,message='大于三位,小于6位'),
validators.Regexp(regex='^[a-zA-Z]+',message='密码以字母开头'),
]
)
repassword = simple.PasswordField(
label='重复密码',
validators=[ 指向前一个字段的 字符串
validators.EqualTo(fieldname='password',message='两次输入不一致!!'),
]
)
gender=core.RadioField(
label='性别:',
coerce=int,
choices=((1,'男'),(2,'女')),
default=1
)
hobby=core.SelectMultipleField( 选择框时 使用core
label='喜好:',
coerce=int,
choices=(
(1,'a'),
(2,'b'),
(3,'c'),
(4,'d'),
),
default=(2,4)
)
submit= simple.SubmitField(
label='提交'
)
2. CBV 校验 :
class LoginClass(views.MethodView):
def get(self):
login=LoginForm() 实例化LoginForm 表单 再传入Html中
return render_template('login.html',login=login)
def post(self):
login=LoginForm(request.form) 用户数据 传入LoginForm做校验 再判断是否校验成功
if login.validate(): True 或False
return 'login success!'
return render_template('login.html',login=login) False 就把错误信息传回Html
app.add_url_rule('/login',view_func=LoginClass.as_view('login'))
class RegClass(views.MethodView):
def get(self):
reg=RegForm()
return render_template('reg.html',reg=reg)
def post(self):
reg=RegForm(request.form)
if reg.validate():
return 'reg success!' reg.get('username') 取值方法
return render_template('reg.html',reg=reg)
app.add_url_rule('/reg',view_func=RegClass.as_view('reg'))
指定RegClass 的路由为/reg 函数为 RegClsass.as_view('reg') reg是随便的
3.页面渲染
<form action="" method="post" novalidate> novalidate 取消浏览器校验是否为空
{% for r in reg %}
<p>{{ r.label }}{{ r }}{{ r.errors.0 }}</p> r.errors 为一个列表
{% endfor %}
</form>
五.数据库池
import pymysql
from DBUtils.PooledDB import PooledDB
POOL = PooledDB(
creator=pymysql, 使用链接数据库的模块
maxconnections=6, 连接池允许的最大连接数,0和None表示不限制连接数
mincached=2, 初始化时,链接池中至少创建的空闲的链接,0表示不创建
maxcached=5, 链接池中最多闲置的链接,0和None不限制
maxshared=3, python中设置没用
blocking=True, 连接池中如果没有可用连接后,是否阻塞等待。True,等待;False不等待然后报错
maxusage=None, 一个链接最多被重复使用的次数,None表示无限制
setsession=[], 开始会话前执行的命令列表。如:["set time zone ..."]
ping=0, 通常为0
host='127.0.0.1',
port=3306,
user='root',
password='',
database='db7',
charset='utf8'
)
def func():
conn = POOL.connection()
cursor = conn.cursor(pymysql.cursors.DictCursor)
cursor.execute('select * from userinfo')
result = cursor.fetchall()
print(result)
conn.close()
func()
六.flask 请求上下文
为解决 多个用户访问 开启多个线程 导致的 request对象 混乱的 现象, 利用 栈,偏函数 ,python 字典 这几个概念
将每个 线程的 key设置为 线程的pid 值为序列化 好 的 request session 对象 取得时候就使用 线程的id 取保证数据的安全性
和高效性,但每一个线程都要复制一个新的地址牺牲了 内存空间
原理参数梳理: 1. environ是请求的信息,2.LocalProxy 偏函数 3.
class wyc():
def __call__(self):
print()
w=wyc()
w() w对象再加括号 相当于执行call方法