文章目录
- 一、请求与响应
- 1)请求对象
- 2)响应对象
- 3)前后端分离和混合
- 二、Session的使用和原理
- 1)Session的使用
- 2)Session源码分析
- 三、Flash闪现
- 四、异步说明
- 五、请求扩展
- 六、BluePrint蓝图
一、请求与响应
1)请求对象
请求对象Request是全局的需要导入使用,这个全局的Request在哪个视图函数中就是当前Request对象 不会混乱
class Test(MethodView):
def get(self):
print(request.method) # 提交地址的提交方法
print(request.args) # get请求提交的数据
print(request.args.get('name')) # 数据中的name
print(request.form) # post请求提交的数据
print(request.values) # get post 提交数据的总和
print(request.cookies) # 客户端所带的Cookie
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) # 请求地址端口
print(request.files) # 请求携带的文件
print(request.data) # Django中的body
2)响应对象
响应四件套
返回模版render_template 重定向redirect 返回Json Jsonify 返回字符串 ''
写入响应头
(在Flask里面没有响应对象 所以我们得做出一个响应对象)
from flask import make_response
def post(self):
res = 'hello'
res = make_response(res)
res.headers['name'] = 'Like' # 往Response的对象中 放入响应头
return res
写入Cookie
res = set_cookie('xxx', 'xxx')
res.delete_cookie('xxx') # 删除Cookie
相关设置
属性 | 说明 |
---|---|
max_age = None | 超时时间Cookie需要延续的时间(以秒为单位)如果参数是None 这个cookie会延续到浏览器关闭为止 |
expires=None | 超时时间(IE requires expires, so set it if hasn’t been already) |
path=‘/’ | Cookie生效的路径,/ 表示根路径,特殊的:根路径的cookie可以被任何url的页面访问,浏览器只会把cookie回传给带有该路径的页面,这样可以避免将cookie传给站点中的其他的应用。 |
domain=None | Cookie生效的域名 你可用这个参数来构造一个跨站cookie。如, domain=”.example.com”所构造的cookie对下面这些站点都是可读的:www.example.com 、 www2.example.com 和an.other.sub.domain.example.com 。如果该参数设置为 None ,cookie只能由设置它的站点读取 |
secure=False | 浏览器将通过HTTPS来回传cookie |
httponly=False | 只能http协议传输,无法被JavaScript获取(不是绝对,底层抓包可以获取到也可以被覆盖) |
3)前后端分离和混合
前后端混合中Cookie是后端写入的
res.set_cookie('xxx', 'xxx')混合模式都是这样写入的 写入之后浏览器会把Cookie保存到Cookie中
本质是后端把Cookie存放到响应头中了 浏览器读到响应头中有Cookie会把Cookie写入到浏览器
前后端分离
直接把客户端要存的Cookie中的数据 放到响应体中 前端自己取出来 放到相应的位置
浏览器使用Js自己写入到Cookie app自己使用代码写入到某个位置
二、Session的使用和原理
1)Session的使用
存入全局的Session
session['name'] = 'Like'
取值全局Session
print(session['name'])
2)Session源码分析
Django的一套 都在 from django.contrib.sessions.middleware import SessionMiddleware里面
Flask请求来了会执行app()
整个flask 从请求进来 到请求走的整个流程
def wsgi_app(self, environ, start_response):
ctx = self.request_context(environ)
try:
try:
ctx.push() # 看下方源码
response = self.full_dispatch_request()
except Exception as e:
error = e
response = self.handle_exception(e)
except:
error = sys.exc_info()[1]
raise
return response(environ, start_response)
finally:
ctx.pop(error)
# ctx.push 的 373行左右
if self.session is None:
session_interface = self.app.session_interface
self.session = session_interface.open_session(self.app, self.request)
if self.session is None:
self.session = session_interface.make_null_session(self.app)
# app.session_interface 就是Flask对象中有个session_interface对象
SecureCookieSessionInterface()
-open_session:请求来了,从cookie中取出三段串,反序列化解密放到session中
-save_session:请求走了,把session字典中的值,序列化加密,放到cookie中
# open_session:请求来了执行
def open_session(self, app, request) :
s = self.get_signing_serializer(app)
if s is None:
return None # 头 荷载 签名
# val 就是取出的三段:eyJhZ2UiOiIxOSIsIm5hbWUiOiJscXoifQ.Y5ac9g.vOomQFqFuaqXWqRQhvSNyc61UIk
val = request.cookies.get('session')
if not val:
return self.session_class()
max_age = int(app.permanent_session_lifetime.total_seconds())
try:
data = s.loads(val, max_age=max_age)
return self.session_class(data)
except BadSignature:
return self.session_class()
# 请求走了,执行save_session
def save_session(self, app, session, response):
name = self.get_cookie_name(app)
domain = self.get_cookie_domain(app)
path = self.get_cookie_path(app)
secure = self.get_cookie_secure(app)
samesite = self.get_cookie_samesite(app)
httponly = self.get_cookie_httponly(app)
if not session: # 如果视图函数放了,不为空 session['name']='lqz'
if session.modified: #
response.delete_cookie(
name,
domain=domain,
path=path,
secure=secure,
samesite=samesite,
httponly=httponly,
)
return
if session.accessed:
response.vary.add("Cookie")
if not self.should_set_cookie(app, session):
return
expires = self.get_expiration_time(app, session)
# 序列化---》加密了
val = self.get_signing_serializer(app).dumps(dict(session)) # type: ignore
# 三段:
response.set_cookie(
name, # session
val, # 三段:
expires=expires,
httponly=httponly,
domain=domain,
path=path,
secure=secure,
samesite=samesite,
)
'''
1. 请求来的时候会执行open_session--->取出cookie,判断是否为空,如果不为空,把它反序列化解密---> 字典--->
转到session对象中----> 视图函数
2. 请求走的时候,会执行save_session---->把session转成字典----> 序列化加密--> 三段---> 放到cookie中
'''
三、Flash闪现
Flash的作用:
访问A页面出现错误 重定向到B页面,要在B页面上展示A页面报错的信息
在某个请求中放入值 另一个请求中取出 取出来后就没了(只能使用一次)
使用
方式1:
设置值:
flash('不好意思,没有权限看') # 可以用多次
取值:
get_flashed_messages() # 取出列表
方式2:
设置值:
flash('111',category='Like')
flash('666',category='you') # 可以使用多次
取值:
rrors = get_flashed_messages(category_filter=['Like'])
四、异步说明
异步框架FastApi
async def index():
print('sdfasd')
a++
await xxx # io操作
async def goods():
pass
框架之前的Web框架开启进程线程---> 一条线程会运行多个协程函数----> 协程函数中遇到io读到await关键字就会切换到别的协程函数
一旦使用了异步所有的模块都要是异步
同步: pymysql reids
异步: aiomysql aioreids
在FastApi或Sanic中要操作Mysql、Redis要需要使用异步的框架否则效率更低
Django3.x 以后页支持async关键字
aiomysql
import asyncio
import aiomysql
loop = asyncio.get_event_loop()
async def test_example():
conn = await aiomysql.connect(host='127.0.0.1', port=3306,
user='root', password='', db='mysql',
loop=loop)
cur = await conn.cursor()
await cur.execute("SELECT Host,User FROM user")
print(cur.description)
r = await cur.fetchall()
print(r)
await cur.close()
conn.close()
loop.run_until_complete(test_example())
aioredis
import aioredis
import asyncio
class Redis:
_redis = None
async def get_redis_pool(self, *args, **kwargs):
if not self._redis:
self._redis = await aioredis.create_redis_pool(*args, **kwargs)
return self._redis
async def close(self):
if self._redis:
self._redis.close()
await self._redis.wait_closed()
async def get_value(key):
redis = Redis()
r = await redis.get_redis_pool(('127.0.0.1', 6379), db=7, encoding='utf-8')
value = await r.get(key)
print(f'{key!r}: {value!r}')
await redis.close()
if __name__ == '__main__':
asyncio.run(get_value('key')) # need python3.7
五、请求扩展
在请求进入视图函数之前执行一些代码,请求出了视图函数以后执行一些代码,类似于django的中间件完成的功能7个装饰器
1. before_request:在请求进视图函数之前执行
多个的话会从上往下依次执行 django:process_request,如果返回四件套之一就直接返回了,在这里面正常使用request对象
2. after_request:在请求从视图函数走之后执行
多个的话会从下往上依次执行 django:process_response一样,要有参数和返回值参数就是response对象 返回值也必须是resposne对象
session、request照常使用
3. before_first_request:项目启动后第一次访问会执行以后再也不执行了
可以做一些初始化的操作
4. teardown_request:每一个请求之后绑定一个函数即使遇到了异常,每个请求走都会执行记录错误日志
@app.teardown_request
def tear_down(e):
print(e) # 如果有异常,这是异常对象
print('我执行了')
5. errorhandler路径不存在时404,服务器内部错误500
@app.errorhandler(404)
def error_404(arg):
print('404会执行我')
return "404错误了"
return render_template('404.html')
@app.errorhandler(500) # debug为False请情况下才能看到
def error_500(arg):
print('500会执行我')
return "服务器内部错误"
6. template_global 标签 在模板中用 {{sb(1,2)}}
@app.template_global()
def sb(a1, a2):
return a1 + a2
7. template_filter过滤器 在模板中用 {{10|db(1,2)}}
@app.template_filter()
def db(a1, a2, a3):
return a1 + a2 + a3
六、BluePrint蓝图
blueprint:对目录进行划分,因为之前所有代码都写在一个py文件中,后期肯定要分到多个文件中
# 蓝图就是为了划分目录的
# 使用步骤:
-1 在不同的view的py文件中,定义蓝图
-2 使用app对象,注册蓝图
-3 使用蓝图,注册路由,注册请求扩展
# 不用蓝图划分目录
# 目录结构
flask_blueprint
-static # 静态文件存放位置
-templates # 模板存放位置
-user.html # 用户html页面
-views # 视图函数的py文件
-__init__.py # 里面定义了Flask的app对象
goods.py # 商品相关视图
user.py # 用户相关视图
app.py #启动文件
# 蓝图小型项目
flask_blueprint_little # 项目名
-src # 项目代码所在路径
-__init__.py # app对象创建的地方
-templates # 模板
-user.html
-static # 静态文件
-views # 视图函数存放位置
-user.py # 用户相关视图
-order.py # 订单相关视图
-manage.py # 启动文件
# 大型项目
flask_blurprint_big # 项目名字
-src # 项目代码所在位置
-__init__.py # src的init,falsk,app实例化
-settings.py # 配置文件
-admin # 类似于django的admin app
-__init__.py # 蓝图初始化
-template # 模板
-backend.html
-static # 静态文件
-xx.jpg
-views.py # 视图层
-models.py # models层,后期咱们表模型
-api
-__init__.py
-template
-static
-models.py
-views.py
-manage.py # 启动文件