1 请求与响应
1.1 请求对象
def index(): # 请求对象,是全局的,需要导入,这个全局的request,在哪个视图函数中,就是当次的request对象,不会乱 # request.method 提交的方法 print(request.method) # request.args get请求提及的数据 print(request.args) print(request.args.get('name')) # request.form post请求提交的数据 print(request.form) # request.values post和get提交的数据总和 print(request.values) # request.cookies 客户端所带的cookie print(request.cookies) # request.headers 请求头 print(request.headers) print('------') # request.path 不带域名,请求路径 print(request.path) # request.full_path 不带域名,带参数的请求路径 print(request.full_path) # request.script_root print('服务端:', request.script_root) # request.url 带域名带参数的请求路径 print(request.url) # request.base_url 带域名请求路径 print(request.base_url) # request.url_root 域名 print(request.url_root) # request.host_url 域名 print(request.host_url) # request.host 127.0.0.1:500 print(request.host) # request.files print(request.files) # obj = request.files['files'] # obj.save('./xx.jpg') print(request.data) # django的body return 'hellod'
1.2 响应对象
@app.route('/',methods=['GET','POST']) def index(): # 1四件套 # -render_template # -redirect # -jsonify # -'' # 2写入响应头-->没有响应对象,先做出一个响应对象 # from .wrappers import Response res='helloe' res=make_response(res) # 往Response的对象中,放入响应头 res.headers['name']='lqz' # 3 写入cookie # res.set_cookie('xx','xx') res.delete_cookie('xx') ''' key, 键 value=’’, 值 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获取(不是绝对,底层抓包可以获取到也可以被覆盖) ''' return res
1.3 前后端分离和混合
# 前后端混合,cookie 是后端写入的 - res.set_cookie('xx','xx') 混合都是这么写的,这样写了,浏览就会把cookie保存到cookie中 -本质是后端把cookie放到响应头中,浏览器读到响应头中有cookie,把cookie写入到浏览器中 # 前后端分离后 -直接把客户端要存到cookie中的数据,放到响应体中 -前端(浏览器,app,小程序),自己取出来,放到相应的位置 浏览器使用js自己写入到cookie app 自己使用代码写入到某个位置
2 session的使用和原理![](/i/l/?n=23&i=blog/2702686/202212/2702686-20221212171926376-1578466339.png)
2.1 session的使用
# 放值 视图函数中 导入全局的session session['name']='bxf' # 取值 视图函数中 导入全局的session print(session['name'])
2.2 源码分析
# django 的这一套,都在 from django.contrib.sessions.middleware import SessionMiddleware # flask 在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, ) # 总结:session的执行流程 1 请求来的时候,会执行open_session--->取出cookie,判断是否为空,如果不为空,把它反序列化,解密---》字典---》转到session对象中----》视图函数 2 请求走的时候,会执行save_session---->把session转成字典----》序列化加密--》三段---》放到cookie中
3 闪现
# flash 翻译过来叫闪现 # 作用: 访问a页面,出了错,重定向到了b页面,要在b页面线上a页面的错误信息 在某个请求中放入值,另一个请求中取出,取出来后就没了 # 使用 设置值: flash('不好意思,没有权限看') 可以用多次 取值:取出列表 get_flashed_messages() # 使用方式二:分类设置和获取 设置值: flash('钱钱钱',category='lqz') flash('666',category='c1')') 可以用多次 取值:取出列表 errors = get_flashed_messages(category_filter=['lqz'])
4 补充异步
# 异步框架 FastAPi async def index(): print('sdfasd') a++ await xxx # io操作 async def goods(): pass # 框架之前的web框架,开启进程,线程---》一条线程会运行多个协程函数----》协程函数中遇到io,读到await关键字,就会切换到别的协程函数 # 一旦使用了异步,以后所有的模块,都要是异步 -pymysql :同步的 -redis :同步 -aiomysql:异步 -aioredis:异步 -在fastapi或sanic中,要操作mysql,redis要使用异步的框架,否则效率更低 -django 3.x 以后页支持async 关键字 -没有一个特别好异步的orm框架 -sqlalchemy在做 -tortoise-orm https://tortoise-orm.readthedocs.io/en/latest/index.html # 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
5 请求扩展
# 在请求进入视图函数之前,执行一些代码 # 请求出了视图函数以后,执行一些代码 # 类似于django的中间件完成的功能 # 7个装饰器 # 1 before_request:在请求进视图函数之前执行 多个的话,会从上往下,依次执行, django:process_request 如果返回四件套之一,就直接返回了 在这里面,正常使用request对象 #2 after_request:在请求从视图函数走之后执行 多个的话,会从下往上,依次执行, django:process_response一样 要有参数,和返回值,参数就是response对象,返回值也必须是resposne对象 session,request 照常使用 向响应头写东西?向cookie中写东西 # 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
6 蓝图
# 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 # 启动文件
标签:flask,基础,self,request,session,cookie,print,app From: https://www.cnblogs.com/shangxin-bai/p/16976990.html