CBV源码闪现请求扩展蓝图g对象flask-session
路由常见写法
@app.route('/index', methods=['GET'], endpoint='index')
def index():
return 'hello'
默认转换器
'default': UnicodeConverter,
'string': UnicodeConverter,
'any': AnyConverter,
'path': PathConverter,
'int': IntegerConverter,
'float': FloatConverter,
'uuid': UUIDConverter,
路由的本质
1.通过源码分析发现route的内层函数是self.add_url_role(rule,edpoint,f,**options)
2.self是当前app对象也就是路由的本质就是app.add_url_role('/index',view_func=index函数)
CBV源码
from flask.views import MethodView
1.写法app.add_url_role('/index',view_func=类.as_view(name='别名且不能冲突'))
2.可以发现as_view()最后返回的是个view的内存地址,请求来了会执行dispath_request(),MethodView重写了dispatch_request()然后也是根据请求方式执行同名的方法
3.一般视图是继承MethodView,而继承View要重写dispatch_request
4.根据源码分析FBV如果不写别名,会默认将函数名作为别名
5.CBV添加装饰器写个类属性
decorators=(装饰器1,装饰器2) # 元组前面的装饰器在装饰器最下面
6.CBV控制访问请求写个属性
methods=['get','post']
add_url_rule参数分析
1.rule:请求的路径,可以使用转化器,用了转换器匹配对应的类型且转换类型
2.endpoint:别名用于反向解析
3.view_func:视图函数的内存地址/类.as_view(name='xxx')
4.methods:允许的请求方式
#其他了解
defaults:字典,作用可以给视图函数传递默认值
strict_slanshes:对url最后的符号是否严格要求
redirect_to:不执行当前函数,直接就是重定向到redirect_to指定的路由
模板
1.模板一般使用的jnjia2与dtl不同,对应字典可以以[],和.get('xx')取值,函数也能直接夹括号得到结果
2.内部处理了xss攻击,原来就是利用了html的特殊字符替换
3.或者直接使用|safe,就会将html字符串渲染
请求响应
from flask import Flask, request,make_response,render_template
# request内的方法
print(request.method) # 请求方式
print(request.args) # get 请求参数
print(request.form) # post提交的数据
print(request.values) # get,post提交的数据总和
print(request.cookies) # cookies
print(request.headers) # 请求头
print(request.path) # 路径
print(request.full_path) # 全路径
print('-----',request.script_root)
print(request.url) # 带服务器地址的全路径
print(request.base_url) # 不带地址的全路径
print(request.url_root) # 域名+端口
print(request.host_url) # 域名+端口
print(request.host) # 不带http的域名+端口
from werkzeug.datastructures import FileStorage
print(type(request.files.get('files')))
2.make_reponse包裹四件套
res=make_response(render_template('home.html'))
res.set_cookie('name','lqz')
3.响应头加数据
res=make_response(render_template('home.html'))
res.headers['X-Something'] = 'A value'
session源码分析
1.app.session_interface--->secureCookieSessionInterface()类的对象
两个重要方法:
open_session:请求来了,取出cookie中的字符串,把字符串反序列化成session对象
save_session:请求走,把session对象,序列化成字符串,放到cookie中
闪现
app.secret_key = 'asdfasdfae4342@@4353' # 依赖session
# flash作用:
这次请求的信息放在flash空间中,能在后面取一次flash空间就会销毁
# 使用
设置值:flash(err)
flash(err,category='xx类')
取值:导入get_flashed_messages
如果没有分类直接这个函数get_flashed_messages()结果就是上次设置的值
有分类err = get_flashed_messages(category_filter=['lqz'])以名取,设置的值取不取下次请求都拿不到了
# 等同于django中的message框架
请求扩展
# 类似django中的中间件
1. before_reuqest # 对应这django中的process_request
-return四件套,不继续往下走了,如果retrun None,继续走下一个请求扩展
-请求来了,就会执行它
-# 重点多个before_request,会从上往下依次执行
2.after_request # 对应这django中的process_response
-必须返回response对象
-请求走了,会执行它
-# 重点多个after_request,从下往上依次执行
3.before_first_request
-项目启动后,第一次访问,会执行
-返回None,会继续往下执行,返回四件套,就不继续往后走了
-无论程序是否出异常,都会触发它
-记录错误日志
-app.debug=False模式才行
4.teardown_request
-无论程序是否出异常,都会触发它
-记录错误日志
-app.debug=False模式才行
5.errorhandler
-监听某个状态码,如果是这个状态码的错误,就会触发它的执行
-可以返回四件套,统一返回格式
# template_global:标签
# 定义
@app.template_global()
def sb(a1, a2):
return a1 + a2
# 模板中使用
{{sb(1,2)}}
# template_filter:过滤器
# 定义
@app.template_filter()
def db(a1, a2, a3):
return a1 + a2 + a3
# 模板中使用
{{ 1|db(2,3)}}
蓝图
# Blue_print:就是目录结构
蓝图的使用:
1 实例化得到蓝图对象 ---可以传一些参数:account = Blueprint('account', __name__,templates,static)
2 把蓝图对象在app中注册---》app.register_blueprint(account,制定前缀)
3 使用蓝图对象,注册路由
4 蓝图有自己的请求扩展--》app对象总的请求扩展,每个蓝图有自己的请求扩展
# 小项目设定目录
-flask_pro #项目名
-pro_flask # 文件夹
-__init__.py # 包的init文件
-static #静态文件
-code.png
-templates #模板文件
-index.html
-views #视图函数写在里面
-account.py #订单相关视图函数
-user.py #用户相关视图函数
-blog.py #博客相关视图函数
-manage.py # 项目的启动文件
pro_flask/init.py
from flask import Flask
app = Flask(__name__,template_folder='templates',static_folder='statics',static_url_path='/static')
from .views.account import account
from .views.blog import blog
# 注册3个蓝图,把他们注册进app中
app.register_blueprint(account)
app.register_blueprint(blog)
pro_flask/views/account.py
from flask import Blueprint
from flask import render_template
# 实例化得到蓝图对象
account = Blueprint('account', __name__)
@account.route('/login.html', methods=['GET', "POST"])
def login():
return render_template('login.html')
pro_flask/views/blog.py
from flask import Blueprint, render_template,request
blog = Blueprint('blog', __name__)
@blog.route('/get_blog')
def get_blog():
print(request.path)
return render_template('blog.html')
manage.py
from pro_flask import app
if __name__ == '__main__':
app.run()
多个app
pro_flask # 项目名
-pro_flask #包名
-admin #admin app的名字
-static #app自己的静态文件
-templates #app自己的模板文件
-__init__.py #包的init
-views.py #app自己的视图函数
-web #web app的名字
-static #app自己的静态文件
-templates #app自己的模板文件
-__init__.py #包的init
-views.py #app自己的视图函数
-__init__.py
-run.py
pro_flask/admin/init.py
from flask import Blueprint
# 第一步:初始化蓝图
admin = Blueprint(
'admin',
__name__,
template_folder='templates', # 指定该蓝图对象自己的模板文件路径
static_folder='static' # 指定该蓝图对象自己的静态文件路径
)
from . import views
pro_flask/admin/views.py
from . import admin
from flask import render_template
@admin.before_request
def before():
print('admin 的 before')
# 第三步:使用蓝图注册路由
@admin.route('/index')
def index():
return render_template('admin.html')
pro_flask/web/init.py
from flask import Blueprint
web = Blueprint(
'web',
__name__,
template_folder='templates',
static_folder='static'
)
from . import views
pro_flask/web/views.py
from . import web
@web.route('/index')
def index():
return 'Web.Index'
pro_flask/init.py
from flask import Flask
from .admin import admin
from .web import web
app = Flask(__name__)
app.debug = True
# 第二步:在app中注册蓝图
app.register_blueprint(admin, url_prefix='/admin') # url_prefix='/admin' 访问这个app的前缀,等同于include
app.register_blueprint(web)
run.py
from pro_flask import app
if __name__ == '__main__':
app.run()
g对象
# g对象其实是为globla关键之,所以写成了魔鬼变量
# 作用就是针对当此请求做一个传值的功能,放值和取值
# 用法
from flask import Flask, g, request,session
app = Flask(__name__)
app.debug=True
@app.before_request
def before():
print(type(g)) # werkzeug.local.LocalProxy 代理模式
print(type(session))
print(type(request))
if request.path == '/':
# request.method='lqz'
g.name = 'lqz' # 放到g对象中
else:
# request.name = 'pyy'
g.name = 'pyy'
def add(a,b):
print(g.name)
# print('-----', request.name)
@app.route('/')
def index():
print(g.name)
# print('-----',request.name)
# add(1,2)
return 'hello'
@app.route('/home')
def home():
print(g.name)
return 'hello'
if __name__ == '__main__':
app.run(host='0.0.0.0', port=8080)
flask-session的使用
# 更改自带的session存放位置
写一个类,写open_session和save_session方法
# 直接使用flask-session第三方支持
from flask_session import RedisSessionInterface
app.session_interface=RedisSessionInterface(redis=None,key_prefix='luffy_'(sessionkey自带前缀))
# 通用方案
from redis import Redis
from flask_session import Session
app.config['SESSION_TYPE'] = 'redis'
app.config['SESSION_KEY_PREFIX'] = 'luffy' # 相当于app.secret_key='a'加session头
app.config['SESSION_REDIS'] = Redis(host='127.0.0.1',port='6379')
Session(app) #后面会经常见这种写法--->类(app)---》包一下的写法
浙公网安备 33010602011771号