内容回顾: 1. git的作用? 2. git命令? git init git add git status git commit git log git reflog git reset --hard git checkout 3. 路飞表结构: - 课程(13表) - 课程大类 - 课程子类 - 学位课 - 讲师 - 奖学金 - 专题课(学位课模块表) - 价格策略(contenttype) - 课程详细(o2o -> 水平分表) - 常见问题 - 课程大纲 - 章节 - 课时 - 作业 - 深科技(4+2) - 用户表 - 用户token - 文章来源 - 文章表 - 通用评论表 - 通用收藏表 4. 谈谈你对 django rest framework框架的认识? - 路由, - 可以通过as_view传参数,根据请求方式不同执行相应的方法 - 可以在url中设置一个结尾,类似于: .json - 视图, - 帮助开发者提供了一些类,并在类中提供了多个方法以供我们使用。 - 版本, - 在url中设置version参数,用户请求时候传入参数。在request.version中获取版本,根据版本不同做不同处理 - 认证, - 写一个类并注册到认证类,在类的的authticate方法中编写认证逻辑。 - 认证成功(user,auth) - raise AuthticateFaild(....) - None - 权限 - 写一个类并注册到权限类,在类的的has_permission方法中编写认证逻辑。 - True - False - 频率限制 - 写一个类并注册到频率类,在类的的 allow_request/wait 方法中编写认证逻辑。 allow_request - True - False 如果返回False,那么就要执行wait - 解析器, - 根据ContentType请求头,选择不同解析器对 请求体中的数据进行解析。 POST /index/ http1.1. host:11.11.11.11 Content-Type:url-formendo.... user=alex&age=123 POST /index/ http1.1. host:11.11.11.11 Content-Type:application/json {....} - 分页 - 对从数据库中获取到的数据进行分页处理: SQL -> limit offset - 根据页码:http://www.luffycity.com/api/v1/student/?page=1&size=10 - 根据索引:http://www.luffycity.com/api/v1/student/?offset=60&limit=10 - 根据加密:http://www.luffycity.com/api/v1/student/?page=erd8 赠送:页码越大速度越慢,为什么以及如何解决? 原因:页码越大向后需要扫描的行数越多,因为每次都是从0开始扫描。 解决: - 限制显示的页数 - 记录当前页数据ID最大值和最小值,再次分页时,根据ID现行筛选,然后再分页。 - 序列化 - 对queryset序列化以及对请求数据格式校验。 - 渲染器 - 根据URL中传入的后缀,决定在数据如何渲染到到页面上。 今日内容: - git - redis 内容详细: 1. git,小东北创业史。 第一阶段:在沙河的日子 第二阶段:开发直播功能,开发过程中临时需要修复bug或临时新功能到来。 方式一: git stash git stash pop git stash 将当前工作区所有修改过的内容存储到“某个地方”,将工作区还原到当前版本未修改过的状态 git stash list 查看“某个地方”存储的所有记录 git stash clear 清空“某个地方” git stash pop 将第一个记录从“某个地方”重新拿到工作区(可能有冲突) git stash apply 编号, 将指定编号记录从“某个地方”重新拿到工作区(可能有冲突) git stash drop 编号,删除指定编号的记录 git stash作用,帮助我们暂时存储已经开发一些功能的代码,继续做其他事情,做完之后,再回来继续开发 方式二: git branch git branch dev git branch bug git branch -d bug git checkout dev git merge bug 面试题:如果代码出现bug,你们是如何解决? 创建一个bug分支,然后进行bug处理,处理完毕后,合并到master分支。 删除bug分支 回到dev分支继续开发。 第三阶段:在三里屯买了一层楼。 需要一个代码托管的网站:github、Bitbucket、码云 自己创建代码托管的网站:gitlab 注册账号: 用户名:邮箱 密码:admin123 命令: git remote add origin ......... git push origin dev git clone https://github.com/WuPeiqi/dbhot.git git pull origin dev git fetch origin dev git merge origin/dev 改: git rebase origin/dev git pull origin master git fetch origin master git merge origin/master
git pull origin master --allow-unrelated-histories
git rebase的作用? 保持提交记录的整洁。 2. redis mysql是一个软件,帮助开发者对一台机器的硬盘进行操作。 redis是一个软件,帮助开发者对一台机器的内存进行操作。 关键字: 缓存,优先去redis中获取,如果没有就是数据库。 安装: - redis软件 - yum install redis redis-server /etc/redis.conf - wget http://download.redis.io/releases/redis-3.0.6.tar.gz tar xzf redis-3.0.6.tar.gz cd redis-3.0.6 make /src/redis-server redis.conf 默认端口:6379 配置文件: bind 0.0.0.0 port 6379 requirepass dskjfsdf - python连接redis的模块 pip3 install redis 基本使用: a. import redis # 创建连接 # conn = redis.Redis(host='47.94.172.250',port=6379,password='luffy1234') # conn.set('x1','wanghuaqiang',ex=5) # val = conn.get('x1') # print(val) b. # 连接池 # import redis # # pool = redis.ConnectionPool(host='10.211.55.4', port=6379,password='luffy1234',max_connections=1000) # conn = redis.Redis(connection_pool=pool) # # conn.set('foo', 'Bar') 连接池注意:连接池只创建一次 总结: 1. git+github 2. redis
s9day110 内容回顾: 1. git开发时,出bug如何结局? 2. git rebase的作用? 3. git 命令? 4. redis是什么? 用于操作内存的软件。 - 可以做持久化: - AOF - RDB - 相当于是大字典 - 单进程单线程 5. 使用连接池 本质,维护一个已经和服务端连接成功的socket。 以后再次发送数据时,直接获取一个socket,直接send数据。 6. 路飞表结果 - 课程 - 大类 - 子类 - 学位课 - 奖学金 - 老师 - 专题课 - 课程详细 - 大纲 - 作业 - 章节 - 课时 - 价格策略 - 深科技 - 文章来源 - 文章 - 用户 - token - 评论 - 收藏 7. 支付宝支付 - 加密方式:rsa - 公钥私钥: - 商户私钥 - 支付宝公钥 - 支付成功后,断电宕机 - 成功:return HttpResponse('success') 8. rest framework框架 9. 数据库页数越大速度越慢。 - 限制页数 - 记录当前页最大ID、最小ID - 错误答案: - 扫描索引表 - 再去数据库表中获取数据 今日内容: 1. git 2. redis 3. 改代码 内容详细: 1. git 第四阶段: 多人协同开发 1. 允许他人操作程序 - 合作者 - 创建组织 2. 分支 - master - dev - xdb - zhh 3. 规则 - 一起合并 - 合并时间:1/2 问题: $ git push origin dev To https://github.com/WuPeiqi/dbhot.git ! [rejected] dev -> dev (fetch first) error: failed to push some refs to 'https://github.com/WuPeiqi/dbhot.git' hint: Updates were rejected because the remote contains work that you do hint: not have locally. This is usually caused by another repository pushing hint: to the same ref. You may want to first integrate the remote changes hint: (e.g., 'git pull ...') before pushing again. hint: See the 'Note about fast-forwards' in 'git push --help' for details. 4. 做代码review 如何做代码review? - 创建review分支: 谁来锁代码review? - 组长 - 带你的人 第五阶段:给别人代码贡献力量 问题: 如果你要在github上给别人代码添加功能? fork pull request 其他: a. 不用反复输入用户名密码登录 Https: https://用户名:密码@github.com/WuPeiqi/dbhot.git git remote add origin https://用户名:密码@github.com/WuPeiqi/dbhot.git SSH: git@github.com:WuPeiqi/dbhot.git b. .gitignore文件 c. 版本 git tag -a v1.0 -m '版本介绍' 本地创建Tag git show v1.0 查看 git tags -n 查看本地Tag git tag -l 'v1.4.2.*' 查看本地Tag,模糊匹配 git tag -d v1.0 删除Tag git push origin :refs/tags/v0.2 更新远程tag git checkout v.10 切换tag git fetch origin tag V1.2 git push origin --tags git pull origin --tags git clone -b v1.0 https://github.com/WuPeiqi/dbhot.git 要求: 1. 组长创建项目(把自己的路飞学城api):master/dev 2. 组长邀请组员尽力啊 3. 组员: - 创建自己分支 - 修改代码,去提交。 2. redis 特点: a. 持久化 b. 单进程、单线程 c. 5大数据类型 redis={ k1:'123', 字符串 k2:[1,2,3,4,4,2,1], 列表 k3:{1,2,3,4}, 集合 k4:{name:123,age:666}, 字典 k5:{('alex',60),('eva-j',80),('rt',70),},有序集合 } 使用字典: - 基本操作 - 慎重使用hgetall, 优先使用 hscan_iter - 计数器 注意事项:redis操作时,只有第一层value支持:list,dict .... 应用(django): 1. 自定义使用redis 2. 使用第三方组件 pip3 install django-redis 配置: CACHES = { "default": { "BACKEND": "django_redis.cache.RedisCache", "LOCATION": "redis://127.0.0.1:6379", "OPTIONS": { "CLIENT_CLASS": "django_redis.client.DefaultClient", "CONNECTION_POOL_KWARGS": {"max_connections": 100} # "PASSWORD": "密码", } } } 使用: import redis from django.shortcuts import render,HttpResponse from django_redis import get_redis_connection def index(request): conn = get_redis_connection("default") return HttpResponse('设置成功') def order(request): conn = get_redis_connection("back") return HttpResponse('获取成功') 高级使用: 1. 全站缓存 2. 单视图 3. 局部页面 补充:rest framework框架访问频率限制推荐放到 redis/memecached
s9day111 内容回归: 1. django rest framework 2. git协同开发 a. 怎么通过git做得协同开发? b. 是否做代码review? c. 开发过程中出现bug如何做? d. git rebase作用? e. 给别人开源代码贡献力量。 f. 使用的github、gitlab ? PS:隐藏明感信息 3. orm操作 - select_related,连表操作,相当于主动做join - prefeth_related,多次单表操作,先查询想要的数据,然后构造条件,如:id=[1,2,3],再次查询其他表根据id做条件。 - only - defer - F - Q - 通过ORM写偏原生SQL: - extra Entry.objects.extra(select={'new_id': "select col from sometable where othercol > %s"}, select_params=(1,)) Entry.objects.extra(where=['headline=%s'], params=['Lennon']) Entry.objects.extra(where=["foo='a' OR bar = 'a'", "baz = 'a'"]) Entry.objects.extra(select={'new_id': "select id from tb where id > %s"}, select_params=(1,), order_by=['-nid']) - raw # 执行原生SQL models.UserInfo.objects.raw('select * from userinfo') # 如果SQL是其他表时,必须将名字设置为当前UserInfo对象的主键列名 models.UserInfo.objects.raw('select id as nid from 其他表') # 为原生SQL设置参数 models.UserInfo.objects.raw('select id as nid from userinfo where nid>%s', params=[12,]) name_map = {'first': 'first_name', 'last': 'last_name', 'bd': 'birth_date', 'pk': 'id'} Person.objects.raw('SELECT * FROM some_other_table', translations=name_map) - 原生SQL from django.db import connection, connections cursor = connection.cursor() # cursor = connections['default'].cursor() cursor.execute("""SELECT * from auth_user where id = %s""", [1]) row = cursor.fetchone() # fetchall()/fetchmany(..) PS: 选择数据库 queryset = models.Course.objects.using('default').all() 4. redis - 是否可以持久化?AOF、RDB - 单进程、单线程 - 5大数据类型 - 字典操作: - scan_iter 5. 跨域 - JSONP - CORS 6. Http协议 & django 生命周期 & wsgi & FBV、CBV 7. 中间件 8. restful 规范 9. 支付 - rsa - 商户私钥+支付宝公钥 - 精度 -宕机 10. 原生Ajax - XMLHttpRequest 今日内容: - redis - 列表 - 微信消息推送 - 支付相关表结构 内容详细: - redis - 左右操作 - 阻塞 - 通过yield创建一个生成器完成一点一点获取(通过字典操作的源码来的灵感) def list_iter(key,count=100): index = 0 while True: data_list = conn.lrange('k1', index, index+count-1) if not data_list: return index += count for item in data_list: yield item PS: 队列:先进先出 栈:后进先出 - 事务+一次发送多个命令: conn = redis.Redis(host='47.94.172.250',port=6379,password='Luffy!4321') pipe = conn.pipeline(transaction=True) pipe.multi() pipe.set('k2','123') pipe.hset('k3','n1',666) pipe.lpush('k4','laonanhai') pipe.execute() - 微信消息推送 - 公众号 - 已认证公众号 - 服务号 - 已认证服务号 - 企业号 基于:微信认证服务号 主动推送微信消息。 前提:关注服务号 环境:沙箱环境 总结: 1. 注册账号 appID:wx89085e915d351cae appsecret:64f87abfc664f1d4f11d0ac98b24c42d 网页授权获取用户基本信息:47.98.134.86 或 域名 2. 关注公众号(已认证的服务号) 3. 生成二维码,用户扫描; 将用户信息发送给微信,微信再将数据发送给设置redirect_uri地址(md5值) 4. 回调地址:47.98.134.86/callback/ - 授权 - 用户md5 - 获取wx_id 在数据库中更新设置:wx_id 5. 发送消息(模板消息) - wx_id - access_token(2小时有效期) - 支付相关: 1. 加入购物车,保存到redis 理由: a. 临时状态 b. 修改购物信息 结构: redis->{ shopping_car:{ 用户ID:{ 课程1:{ title:'金融量化分析入门', img:'/xx/xx/xx.png', policy:{ 10: {'name':'有效期1个月','price':599}, 11: {'name':'有效期3个月','price':1599}, 13: {'name':'有效期6个月','price':2599}, }, default_policy:12 }, 课程2:{ title:'金融量化分析入门', img:'/xx/xx/xx.png', policy:{ 10: {'name':'有效期1个月','price':599}, 11: {'name':'有效期3个月','price':1599}, 13: {'name':'有效期6个月','price':2599}, }, default_policy:10 } }, 用户ID:{...}, } } POST请求:购物车中添加一条数据 请求体: { courseid:1, policy_id:10 } 后台: 检验当前课程是否有此价格策略,合法:将数据构造字典,再添加到redis GET请求:查看自己购物车中的所有数据 获取当前登录用户ID,根据用户ID去redis的购物车中获取数据。 DELETE请求:删除购物车中的数据 请求体: { course_ids:[1,2] } PUT/PATCH请求:更新价格策略 请求体: { courseid:1, policy_id:13 } 注意:不要写vue、不要写vue、不要写vue 2. 结算中心 3. 去支付 总结: 1. redis列表操作 - 前后都可以 - 等 - yield - pipeline 2. 微信消息推送 - 已认证服务号 - 模板消息 - 生成二维码 3. 路飞购物车 - 为什么使用redis? - 字典是如何构造? 作业: 1. django orm操作 2. 购物车 - django-redis组件
s9day112 内容回顾: 1. redis列表 - 左右 - hang住 - 通过yield构造生成器 写一个栈:写一个类实现后进先出的结构。 class FooStack(object): def push(self): pass def pop(self): pass 2. redis字典 - hscan_iter 3. 事务 4. 连接池 5. 单进程单线程 6. 持久化: - AOF - RDB 7. 微信消息推送 - 自动获取 wx_id - 根据用户 wx_id向用户推送消息 - 已认证的服务号 8. 支付宝支付 - 加密:RSA - 秘钥:商户私钥+支付宝公钥 - 宕机:重发 - 精度:1.11 9. ORM - only - defer - select_related - prefetch_related - 偏原生 - raw - extra - connection - .using('default') - .exclude(id=5) 今日内容: - 加入购物车 作业: - 结算中心 内容详细: - 加入购物车 1. 配置 CACHES = { "default": { "BACKEND": "django_redis.cache.RedisCache", "LOCATION": "redis://140.143.227.206:6379", "OPTIONS": { "CLIENT_CLASS": "django_redis.client.DefaultClient", "CONNECTION_POOL_KWARGS": {"max_connections": 100}, "PASSWORD": "1234", } } } 2. 路由 3. 认证组件 4. 业务(合法性) - 增 - 删 - 改 - 查 作业: a. 实现购物车逻辑 b. 结算中心 1.购物车(可以选择价格策略) { luffy_shopping_car_6_11:{ 'title':'21天入门到放弃', 'src':'xxx.png', 'policy':{ 1:{id:'xx'.....}, 2:{id:'xx'.....}, 3:{id:'xx'.....}, 4:{id:'xx'.....}, }, 'default_policy':3 }, luffy_shopping_car_6_13:{ ... } } 2.结算(可以选择优惠券) a. POST请求,去结算 请求体: { courseids:[1,2] } 业务处理: 1. 检测课程ID是否已经加入到购物车 2. 获取指定价格策略信息 3. 获取优惠券信息 4. 构造结构放入redis b. GET请求,获取结算中心数据 业务处理: 1. 获取结算中心里的课程信息(绑定课程优惠券) 2. 获取全局优惠券 c. PATCH请求,选择优惠券 请求体: { courseid:0 couponid:12 } 业务处理: 1. 校验结算中心是否存在该课程 2. 校验优惠券是否可用 注意: 1. 优惠券状态 2. 优惠券使用时间
s9day113 内容回顾: 1. 路飞学城的购物车如何实现? 2. 商品是否有个数? - 价格策略(用事件来类比个数) - 购买之后就开始计时 3. 购物车在redis的结构? 4. 购物车购买数量有限制吗? .keys('xxxxx') 5. 购物车是否设置超时时间? .conn.expire("shopping_car_1_1" ,60*30) 方案:购买课程个数限制(200个) 6. 为什么把购物车信息放入redis? - 临时状态 - 频繁修改的话,速度快。 7. 具体购物车的逻辑? 添加: 1. 用户选择:课程、价格策略,提交 2. 获取课程、价格策略进行合法性校验(数据库查询) 3. 数据获取,构造结构: { shopping_car_用户ID_课程ID:{ title:"...", img:'xxx', policy:{ ... } } } 4. 将数据以字典的形式保存到redis中。 修改: 1. 用户选择:课程、价格策略,提交 2. 获取课程、价格策略进行合法性校验(redis查询) 3. 更新价格策略 删除: 1. 用户选择:课程提交 2. 获取课程合法性校验(redis查询) 3. 删除 查看: 1. 构造Key shopping_car_用户ID_* 2. scan_iter 8. 原则: - 简答逻辑先处理 - try - 细粒度异常+自定义异常 - 导入模块 - 内置 - 框架 - 自定义 - 注释 - 文件 - 类 - 函数 - 文件名、类、函数、project - 对功能进行分类 - 减少代码层级 - BaseResponse 今日内容: - 结算中心 - 去支付 内容详细: 1. 结算中心 a. 添加到结算中心: 请求:POST 数据: { courseids:[1,2] } Q补充: con = { "id":1, "age__gt":9, "name__lt": 8 "name__lt": 8 } # 构造AND models.User.objects.filter(**con) # 构造复杂(条件写死) con = Q(Q(account=request.auth.user) & Q(status=0)) | Q(coupon__valid_begin_date__lte=ctime) models.User.objects.filter(con) # 构造负责(条件动态) q1 = Q() q1.connector = 'OR' for k,v in con.items(): q1.children.append((k,v,)) models.User.objects.filter(q1) 结算数据及目标: payment_dict = { '2': { course_id:2, 'title': 'CRM客户关系管理系统实战开发-专题', 'img': 'CRM.jpg', 'policy_id': '4', 'coupon': {}, 'default_coupon': 0, 'period': 210, 'period_display': '12个月', 'price': 122.0}, '1': { course_id:2, 'title': '爬虫开发-专题', 'img': '爬虫开发-专题.jpg', 'policy_id': '2', 'coupon': { 4: {'coupon_type': 0, 'coupon_display': '立减券', 'money_equivalent_value': 40}, 6: {'coupon_type': 1, 'coupon_display': '满减券', 'money_equivalent_value': 60, 'minimum_consume': 100} }, 'default_coupon': 0, 'period': 60, 'period_display': '2个月', 'price': 599.0} } global_coupon_dict = { 'coupon': { 2: {'coupon_type': 1, 'coupon_display': '满减券', 'money_equivalent_value': 200, 'minimum_consume': 500} }, 'default_coupon': 0 } ========================================= redis ============================================== redis = { payment_1_2:{ course_id:2, 'title': 'CRM客户关系管理系统实战开发-专题', 'img': 'CRM.jpg', 'policy_id': '4', 'coupon': {}, 'default_coupon': 0, 'period': 210, 'period_display': '12个月', 'price': 122.0}, }, payment_1_1:{ course_id:1, 'title': '爬虫开发-专题', 'img': '爬虫开发-专题.jpg', 'policy_id': '2', 'coupon': { 4: {'coupon_type': 0, 'coupon_display': '立减券', 'money_equivalent_value': 40}, 6: {'coupon_type': 1, 'coupon_display': '满减券', 'money_equivalent_value': 60, 'minimum_consume': 100} }, 'default_coupon': 0, 'period': 60, 'period_display': '2个月', 'price': 599.0} }, payment_global_coupon_1:{ 'coupon': { 2: {'coupon_type': 1, 'coupon_display': '满减券', 'money_equivalent_value': 200, 'minimum_consume': 500} }, 'default_coupon': 0 } }
s9day114 内容回顾: 1. 为什么要开发“学城”? - 提高在线 完课率(学成率)。 - 具体: - 购买时间周期 - 闯关式学习 - 考核 - 导师筛选 - 导师监督(跟进记录) - 答疑时间(12小时) - 奖惩措施 - 时间 - 作业 2. 开发周期和团队? 团队: - 开发 - 导师后台,stark组件+rbac : 1人 - 管理后台,stark组件+rbac : 1人 - 主站 - vue.js 1人 - api 村长+1/2文州+1/2Alex+其他 + 村长 - 运维(1人) - 测试(1人) - 产品经理(1人) - UI设计(1人) - 运营(1人) - 销售(4人) - 全职导师(2人) - 签约讲师(...) 周期: - 7月份 - 11月份上线 - 11月份~次年5月份: 修Bug,活动支持,广告。。。 - 6月份:开发题库系统 3. 购买流程 - 加入购物车 - 去结算 - 去支付 今日内容: - 去支付 - Flask - 基础 - 第三方组件 - 上下文管理聊源码 内容详细: 1. 去支付(面向专题课) POST请求: URL: https://www.luffycity.com/course/order/?token=123879shdfkjshdf123 请求体: { balance:1000, money:900 } 业务处理: ... 2. Flask - pip3 install flask - 短小精悍、可扩展强 的一个Web框架。 注意:上下文管理机制 - 依赖wsgi:werkzurg - 学习werkzurg: 示例一: from werkzeug.wrappers import Request, Response from werkzeug.serving import run_simple def run(environ,start_response): return [b"asdfasdf"] if __name__ == '__main__': run_simple('localhost', 4000, run) 示例二: from werkzeug.wrappers import Request, Response @Request.application def hello(request): return Response('Hello World!') if __name__ == '__main__': from werkzeug.serving import run_simple run_simple('localhost', 4000, hello) - 学习Flask 作业: """ 1. 获取用户提交数据 { balance:1000, money:900 } balance = request.data.get("balance") money = request.data.get("money") 2. 数据验证 - 大于等于0 - 个人账户是否有1000贝里 if user.auth.user.balance < balance: 账户贝里余额不足 优惠券ID_LIST = [1,3,4] 总价 实际支付 3. 去结算中获取课程信息 for course_dict in redis的结算中获取: # 获取课程ID # 根据course_id去数据库检查状态 # 获取价格策略 # 根据policy_id去数据库检查是否还依然存在 # 获取使用优惠券ID # 根据优惠券ID检查优惠券是否过期 # 获取原价+获取优惠券类型 - 立减 0 = 获取原价 - 优惠券金额 或 折后价格 = 获取原价 - 优惠券金额 - 满减:是否满足限制 折后价格 = 获取原价 - 优惠券金额 - 折扣: 折后价格 = 获取原价 * 80 / 100 4. 全站优惠券 - 去数据库校验全站优惠券的合法性 - 应用优惠券: - 立减 0 = 实际支付 - 优惠券金额 或 折后价格 =实际支付 - 优惠券金额 - 满减:是否满足限制 折后价格 = 实际支付 - 优惠券金额 - 折扣: 折后价格 = 实际支付 * 80 / 100 - 实际支付 5. 贝里抵扣 6. 总金额校验 实际支付 - 贝里 = money:900 7. 为当前课程生成订单 - 订单表创建一条数据 Order - 订单详细表创建一条数据 OrderDetail EnrolledCourse - 订单详细表创建一条数据 OrderDetail EnrolledCourse - 订单详细表创建一条数据 OrderDetail EnrolledCourse - 如果有贝里支付 - 贝里金额扣除 Account - 交易记录 TransactionRecord - 优惠券状态更新 CouponRecord 注意: 如果支付宝支付金额0, 表示订单状态:已支付 如果支付宝支付金额110,表示订单状态:未支付 - 生成URL(含订单号) - 回调函数:更新订单状态 """
s9day115 Flask基础 回顾: 1.谈谈你对django和flask的认识。 2.flask和django最大的不同点:request/session 3.flask知识点 - 模板+静态文件,app= Flask(__name__,....) - 路由 @app.route('/index',methods=["GET"]) - 请求 request.form request.args request.method - 响应 "" render redirect - session session['xx'] = 123 session.get('xx') 4. 路飞总共有几个项目 - 管理后台 - 导师后台 - 主站 5. 路飞主站业务 - 课程 - 课程列表 - 课程详细 - 大纲、导师、推荐课程 - 价格策略 - 章节和课时 - 常见问题 - 深科技 - 文章列表 - 文章详细 - 收藏 - 评论 - 点赞 - 支付 - 购物车(4) - 结算中心(3) - 立即支付(1) 知识点: - redis - 支付宝 - 消息推送 - 构建数据结构 - 优惠券+贝里+支付宝 - 个人中心 - 课程中心 6. 播放视频:CC视频 - 加密 - 非加密 今日内容: 1. 配置文件 2. 路由系统 3. 视图 4. 请求相关 5. 响应 6. 模板渲染 7. session 8. 闪现 9. 中间件 10. 蓝图(blueprint) 11. 特殊装饰器 内容详细: 知识点: - 给你一个路径 “settings.Foo”,可以找到类并获取去其中的大写的静态字段。 settings.py class Foo: DEBUG = True TEST = True xx.py import importlib path = "settings.Foo" p,c = path.rsplit('.',maxsplit=1) m = importlib.import_module(p) cls = getattr(m,c) # 如果找到这个类? for key in dir(cls): if key.isupper(): print(key,getattr(cls,key)) 1. 配置文件 app.config.from_object("settings.DevelopmentConfig") class Config(object): DEBUG = False TESTING = False DATABASE_URI = 'sqlite://:memory:' class ProductionConfig(Config): DATABASE_URI = 'mysql://user@localhost/foo' class DevelopmentConfig(Config): DEBUG = True class TestingConfig(Config): TESTING = True 2. 路由系统 - endpoint,反向生成URL,默认函数名 - url_for('endpoint') / url_for("index",nid=777) - 动态路由: @app.route('/index/<int:nid>',methods=['GET','POST']) def index(nid): print(nid) return "Index" 3. FBV 4. 请求相关 # 请求相关信息 # request.method # request.args # request.form # request.values # request.cookies # request.headers # request.path # request.full_path # request.script_root # request.url # request.base_url # request.url_root # request.host_url # request.host # request.files # obj = request.files['the_file_name'] # obj.save('/var/www/uploads/' + secure_filename(f.filename)) 5. 响应: 响应体: return “asdf” return jsonify({'k1':'v1'}) return render_template('xxx.html') return redirect() 定制响应头: obj = make_response("asdf") obj.headers['xxxxxxx'] = '123' obj.set_cookie('key', 'value') return obj 示例程序:学生管理 版本一: @app.route('/index') def index(): if not session.get('user'): return redirect(url_for('login')) return render_template('index.html',stu_dic=STUDENT_DICT) 版本二: import functools def auth(func): @functools.wraps(func) def inner(*args,**kwargs): if not session.get('user'): return redirect(url_for('login')) ret = func(*args,**kwargs) return ret return inner @app.route('/index') @auth def index(): return render_template('index.html',stu_dic=STUDENT_DICT) 应用场景:比较少的函数中需要额外添加功能。 版本三:before_request @app.before_request def xxxxxx(): if request.path == '/login': return None if session.get('user'): return None return redirect('/login') 6. 模板渲染 - 基本数据类型:可以执行python语法,如:dict.get() list['xx'] - 传入函数 - django,自动执行 - flask,不自动执行 - 全局定义函数 @app.template_global() def sb(a1, a2): # {{sb(1,9)}} return a1 + a2 @app.template_filter() def db(a1, a2, a3): # {{ 1|db(2,3) }} return a1 + a2 + a3 - 模板继承 layout.html <!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title>Title</title> <meta name="viewport" content="width=device-width, initial-scale=1"> </head> <body> <h1>模板</h1> {% block content %}{% endblock %} </body> </html> tpl.html {% extends "layout.html"%} {% block content %} {{users.0}} {% endblock %} - include {% include "form.html" %} form.html <form> asdfasdf asdfasdf asdf asdf </form> - 宏 {% macro ccccc(name, type='text', value='') %} <h1>宏</h1> <input type="{{ type }}" name="{{ name }}" value="{{ value }}"> <input type="submit" value="提交"> {% endmacro %} {{ ccccc('n1') }} {{ ccccc('n2') }} - 安全 - 前端: {{u|safe}} - 前端: MarkUp("asdf") 7. session 当请求刚到来:flask读取cookie中session对应的值:eyJrMiI6NDU2LCJ1c2VyIjoib2xkYm95,将该值解密并反序列化成字典,放入内存以便视图函数使用。 视图函数: @app.route('/ses') def ses(): session['k1'] = 123 session['k2'] = 456 del session['k1'] return "Session" session['xxx'] = 123 session['xxx'] 当请求结束时,flask会读取内存中字典的值,进行序列化+加密,写入到用户cookie中。 8. 闪现,在session中存储一个数据,读取时通过pop将数据移除。 from flask import Flask,flash,get_flashed_messages @app.route('/page1') def page1(): flash('临时数据存储','error') flash('sdfsdf234234','error') flash('adasdfasdf','info') return "Session" @app.route('/page2') def page2(): print(get_flashed_messages(category_filter=['error'])) return "Session" 9. 中间件 - call方法什么时候出发? - 用户发起请求时,才执行。 - 任务:在执行call方法之前,做一个操作,call方法执行之后做一个操作。 class Middleware(object): def __init__(self,old): self.old = old def __call__(self, *args, **kwargs): ret = self.old(*args, **kwargs) return ret if __name__ == '__main__': app.wsgi_app = Middleware(app.wsgi_app) app.run() 10. 特殊装饰器 1. before_request 2. after_request 示例: from flask import Flask app = Flask(__name__) @app.before_request def x1(): print('before:x1') return '滚' @app.before_request def xx1(): print('before:xx1') @app.after_request def x2(response): print('after:x2') return response @app.after_request def xx2(response): print('after:xx2') return response @app.route('/index') def index(): print('index') return "Index" @app.route('/order') def order(): print('order') return "order" if __name__ == '__main__': app.run() 3. before_first_request from flask import Flask app = Flask(__name__) @app.before_first_request def x1(): print('123123') @app.route('/index') def index(): print('index') return "Index" @app.route('/order') def order(): print('order') return "order" if __name__ == '__main__': app.run() 4. template_global 5. template_filter 6. errorhandler @app.errorhandler(404) def not_found(arg): print(arg) return "没找到" 总结: - 配置文件 - 路由 - 视图:FBV - 请求 - 响应 obj = make_response("adfasdf") obj.headers['x'] = asdfasdf return obj - 模板 - session - flash - 中间件 - 特殊装饰器