Flask的请求,响应简介
Flask的请求与响应
| def index(): |
| |
| |
| print(request.method) |
| |
| print(request.args) |
| print(request.args.get('name')) |
| |
| print(request.form) |
| |
| print(request.values) |
| |
| print(request.cookies) |
| |
| print(request.headers) |
| print('------') |
| |
| 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) |
| return 'hellod' |
| @app.route('/',methods=['GET','POST']) |
| def index(): |
| |
| |
| |
| |
| |
| |
| |
| res='helloe' |
| res=make_response(res) |
| |
| res.headers['name']='lqz' |
| |
| |
| 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 |
| |
| - res.set_cookie('xx','xx') 混合都是这么写的,这样写了,浏览就会把cookie保存到cookie中 |
| -本质是后端把cookie放到响应头中,浏览器读到响应头中有cookie,把cookie写入到浏览器中 |
| |
| -直接把客户端要存到cookie中的数据,放到响应体中 |
| -前端(浏览器,app,小程序),自己取出来,放到相应的位置 |
| 浏览器使用js自己写入到cookie |
| app 自己使用代码写入到某个位置 |
session的使用与源码分析
| |
| 导入全局的session |
| session['name']='lqz' |
| |
| |
| 导入全局的session |
| print(session['name']) |
| |
| |
| |
| |
| -请求来了,会执行 app() |
| |
| |
| |
| 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) |
| |
| |
| |
| |
| 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) |
| |
| |
| SecureCookieSessionInterface() |
| -open_session:请求来了,从cookie中取出三段串,反序列化解密放到session中 |
| -save_session:请求走了,把session字典中的值,序列化加密,放到cookie中 |
| |
| |
| |
| |
| def open_session(self, app, request) : |
| s = self.get_signing_serializer(app) |
| if s is None: |
| return None |
| |
| 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() |
| |
| |
| |
| 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: |
| 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)) |
| |
| response.set_cookie( |
| name, |
| val, |
| expires=expires, |
| httponly=httponly, |
| domain=domain, |
| path=path, |
| secure=secure, |
| samesite=samesite, |
| ) |
| |
| |
| |
| |
| |
| |
| 1 请求来的时候,会执行open_session--->取出cookie,判断是否为空,如果不为空,把它反序列化,解密---》字典---》转到session对象中----》视图函数 |
| |
| 2 请求走的时候,会执行save_session---->把session转成字典----》序列化加密--》三段---》放到cookie中 |
闪现
| |
| |
| 访问a页面,出了错,重定向到了b页面,要在b页面线上a页面的错误信息 |
| 在某个请求中放入值,另一个请求中取出,取出来后就没了 |
| |
| |
| 设置值: |
| flash('不好意思,没有权限看') |
| 可以用多次 |
| 取值:取出列表 |
| get_flashed_messages() |
| |
| |
| |
| 设置值: |
| flash('钱钱钱',category='lqz') |
| flash('666',category='c1')') |
| 可以用多次 |
| 取值:取出列表 |
| errors = get_flashed_messages(category_filter=['lqz']) |
| |
| |
| |
| # djagno中有同样的,message 框架 研究一下,用一用 |
| |
关于异步的补充
| |
| async def index(): |
| print('sdfasd') |
| a++ |
| await xxx |
| async def goods(): |
| pass |
| |
| |
| |
| |
| -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 |
| |
| |
| |
| 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()) |
| |
| |
| |
| 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')) |
请求扩展
| |
| |
| |
| |
| |
| |
| 多个的话,会从上往下,依次执行, django:process_request |
| 如果返回四件套之一,就直接返回了 |
| 在这里面,正常使用request对象 |
| |
| |
| 多个的话,会从下往上,依次执行, django:process_response一样 |
| 要有参数,和返回值,参数就是response对象,返回值也必须是resposne对象 |
| session,request 照常使用 |
| 向响应头写东西?向cookie中写东西 |
| |
| |
| |
| |
| 可以做一些初始化的操作 |
| |
| |
| |
| @app.teardown_request |
| def tear_down(e): |
| print(e) |
| print('我执行了') |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| @app.errorhandler(500) |
| def error_500(arg): |
| print('500会执行我') |
| return "服务器内部错误" |
| |
| |
| |
| |
| @app.template_global() |
| def sb(a1, a2): |
| return a1 + a2 |
| |
| |
| @app.template_filter() |
| def db(a1, a2, a3): |
| return a1 + a2 + a3 |
蓝图
| |
| |
| |
| -1 在不同的view的py文件中,定义蓝图 |
| -2 使用app对象,注册蓝图 |
| -3 使用蓝图,注册路由,注册请求扩展 |
| |
| |
| |
| flask_blueprint |
| -static |
| -templates |
| -user.html |
| -views |
| -__init__.py |
| goods.py |
| user.py |
| app.py |
| |
| |
| flask_blueprint_little |
| -src |
| -__init__.py |
| -templates |
| -user.html |
| -static |
| -views |
| -user.py |
| -order.py |
| -manage.py |
| |
| |
| |
| flask_blurprint_big |
| -src |
| -__init__.py |
| -settings.py |
| -admin |
| -__init__.py |
| -template |
| -backend.html |
| -static |
| -xx.jpg |
| -views.py |
| -models.py |
| -api |
| -__init__.py |
| -template |
| -static |
| -models.py |
| -views.py |
| -manage.py |
| |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
2022-08-01 选课系统前戏