内容回顾:
. django请求生命周期 -> 执行遵循wsgi协议的模块(socket服务端)
-> 中间件(路由匹配)
-> 视图函数(业务处理:ORM、模板渲染)
-> 中间件
-> wsgi返回 . 什么wsgi
web服务网关接口
实现该协议的模块:
- wsgiref
- werkzurg
- uwsig . 视图
- FBV
url - 函数
- CBV
url - view . djang rest framework . restful 规范()
什么是接口?
- URL
- 约束
# 约束继承(实现)了他的类中必须含有IFoo中的方法
interface IFoo:
def func(self): pass class Foo(IFoo):
def func(self):
print() . 根据method不同,进行不同操作
GET/POST/PUT/DELETE/PATCH
. 面向资源编程
http://www.luffycity.com/salary . 体现版本
http://www.luffycity.com/v1/salary
http://www.luffycity.com/v2/salary https://v4.bootcss.com/
https://v3.bootcss.com/
. 体现是API
http://www.luffycity.com/api/v1/salary
http://www.luffycity.com/api/v2/salary http://api.luffycity.com/v1/salary
http://api.luffycity.com/v2/salary
. https
https://www.luffycity.com/api/v1/salary
https://www.luffycity.com/api/v2/salary . 响应式设置状态码 return HttpResponse('adfasdf',status=) . 条件
https://www.luffycity.com/api/v2/salary?page=1&size=10 . 返回值
https://www.luffycity.com/api/v2/salary
GET: 所有列表
{
code: ,
data: [
{'id':,'title':'高亮'},
{'id':,'title':'龙泰'},
{'id':,'title':'小东北'},
]
} POST: 返回新增的数据
{'id':,'title':'高亮'} https://www.luffycity.com/api/v2/salary/1/
GET: 获取单条数据
{'id':,'title':'高亮'}
PUT:更新
{'id':,'title':'高亮'}
PATCH: 局部更新
{'id':,'title':'高亮'}
DELETE:删除 . 返回错误信息
{
code: ,
error: 'xxx错误'
} . Hypermedia API
ret = {
code: ,
data:{
id:,
name:'小强',
depart_id:http://www.luffycity.com/api/v1/depart/8/
}
} 建议大家使用restful规范 . django rest framework框架()
- 权限
- 认证
- 访问频率限制
- 序列化
- 路由
- 视图
面试题:你的写的类都继承过哪些类?
class View(object): class APIView(View): class GenericAPIView(views.APIView): class GenericViewSet(ViewSetMixin, generics.GenericAPIView) class ModelViewSet(mixins.CreateModelMixin,
mixins.RetrieveModelMixin,
mixins.UpdateModelMixin,
mixins.DestroyModelMixin,
mixins.ListModelMixin,
GenericViewSet):
- 分页
- 解析器
- 渲染器
- 版本 今日内容:
- vue
- restful api 内容详细:
. 渲染器
规定页面显示的效果(无用)
. 版本
原理:要了解
使用:
. 添加配置
REST_FRAMEWORK = { .... 'DEFAULT_VERSIONING_CLASS':'rest_framework.versioning.URLPathVersioning',
'ALLOWED_VERSIONS':['v1','v2'], # 允许的版本
'VERSION_PARAM':'version', # 参数
'DEFAULT_VERSION':'v1', # 默认版本
....
} . 设置路由 s9luffycity/urls.py
urlpatterns = [
#url(r'^admin/', admin.site.urls),
url(r'^api/(?P<version>\w+)/', include('api.urls')),
] api/urls.py
urlpatterns = [
url(r'^course/$', course.CourseView.as_view()),
] . 获取版本
request.version 获取版本 . vue+rest framework
vue:
- 路由 + 组件
- axios发送ajax请求
- that
api:
- 跨域 补充:
- 域名不同
- 端口不同
cors:
本质设置响应头 # 允许你的域名来获取我的数据
response['Access-Control-Allow-Origin'] = "*" # 允许你携带Content-Type请求头
response['Access-Control-Allow-Headers'] = "Content-Type" # 允许你发送DELETE,PUT
response['Access-Control-Allow-Methods'] = "DELETE,PUT" 作业:
.创建两张表
课程表:
id title
Python全栈
Python周末
Linux
课程详细表:
id name course_id
Python基础
Python进阶
Python网络
Python并发
Python数据库
Python前端 . 两个页面
- 课程列表
- 课程详细
内容回顾:
- restful 规范()
- django rest framework框架()
- 跨域
- 为什么会有跨域?
- 绕过浏览器同源策略就可以跨域。
- jsonp
动态创建script标签
同源策略会阻止ajax请求;不阻止具有src属性的标签
<script src='xxxx'></script>
- cors
设置响应头 今日内容:
- vue
- api 内容详细:
. vue
- 课程列表
- 课程详细 - 任务:
- 课程表
id title course_img level(choices)
- 课程详细(one2one 课程 )
id why 推荐课程
- 章节
id name
- 功能:
a. 课程列表显示图片 b. 课程详细显示:
- 为什么要学习这个课程
- 所有推荐课程
- 所有章节 . api
. 查询所有的课程
http://127.0.0.1:8000/api/v1/course/
练习:level变中文 . 查询课程详细
http://127.0.0.1:8000/api/v1/course/1/
- 路由 as_view 是否添加参数,取决于视图继承的类
- 序列化
- depth
- source
- 自定义method 练习:显示该课程相关的所有章节 this补充:
题目1:
var name = '景女神' function Foo(name,age){
this.name = name;
this.age = age;
this.getName = function(){
console.log(this.name); # 文州 (function(){
console.log(this.name); # 女神
})() }
} obj = new Foo('文州',)
obj.getName() 题目2:
var name = '景女神' function Foo(name,age){
this.name = name;
this.age = age;
this.getName = function(){
console.log(this.name); # 文州
var that = this
(function(){
console.log(that.name); # 文州
})() }
} obj = new Foo('文州',) obj.getName() 题目3:
var name = '景女神'
obj = {
name:'文州',
age: ,
getName:function(){
console.log(this.name); # 文州
var that = this
(function(){
console.log(that.name); # 文州
})()
}
}
obj.getName() 作业:
. 前后端流程
. 图片
. CC视频账号
. git相关
- 安装git软件
- 注册github账号
内容回顾:
. 你理解的Http协议?
- 建立在tcp之上
- 一次请求一次响应然后断开连接(无状态、短连接)
- 请求和响应
发送:请求头\r\n\r\n请求体
host:www.luffy.com\r\ncontent-type:application/json\r\n\r\n请求体
响应:响应头\r\n\r\n响应体
...
. django请求生命周期 . wsgi . django中间件是什么? . 使用中间件做过什么?
- 内置
- csrf
- session
- 自定义
- 登录认证
- 权限
- cors
. 中间件中有多少个方法?
5个 . FBV和CBV是什么?以及优缺点。 . rest api . django rest framework框架 . 视图常见的继承
from rest_framework.views import APIView # *
from rest_framework.generics import GenericAPIView
from rest_framework.viewsets import GenericViewSet # as_view
from rest_framework.viewsets import ModelViewSet # * . 如何实现的访问频率控制?
匿名用户:无法控制,因为用户可以换代理IP
{
192.168.1.1:[1521223123.232, 1521223122.232, 1521223121.232],
192.168.1.2:[1521223123.232, 1521223122.232, 1521223121.232],
192.168.1.3:[1521223123.232, 1521223122.232, 1521223121.232],
192.168.1.4:[1521223123.232, 1521223122.232, 1521223121.232],
192.168.1.5:[1521223123.232, 1521223122.232, 1521223121.232],
192.168.1.6:[1521223123.232, 1521223122.232, 1521223121.232],
} 登录用户:如果有很多账号,也无法限制
{
alex:[1521223123.232, 1521223122.232, 1521223121.232],
eric:[1521223123.232, 1521223122.232, 1521223121.232],
} 参考源码:from rest_framework.throttling import SimpleRateThrottle . 序列化
- source
- method 今日内容:
. 示例
- 推荐课程
- 用户登录
- 拦截器 VUE:
- 课程列表:this.$axios + this
- 课程详细:this.$axios + this
- 用户登录:
- this.$axios
- this
- 跨域简单和复杂请求
- vuex做全局变量
- vuex-cookies
- 微职位
- 拦截器
- 携带token PS: api可以同一放在store中保存 API:
- 课程列表
- 序列化:source='get_level_display'
- 课程详细:
- 序列化:source='get_level_display'
- 序列化:method
- 用户登录
- update_or_create
- 微职位
- 认证组件 关联组件:
- 版本
- 解析器
- 渲染器
- 序列化
- 认证组件
- 视图
- 路由 . django组件:contenttype
组件的作用:可以通过两个字段让表和N张表创建FK关系 表结构:
from django.db import models
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation class DegreeCourse(models.Model):
"""学位课程"""
name = models.CharField(max_length=, unique=True)
course_img = models.CharField(max_length=, verbose_name="缩略图")
brief = models.TextField(verbose_name="学位课程简介", ) class Course(models.Model):
"""专题课程"""
name = models.CharField(max_length=, unique=True)
course_img = models.CharField(max_length=) # 不会在数据库生成列,只用于帮助你进行查询
policy_list = GenericRelation("PricePolicy") class PricePolicy(models.Model):
"""价格与有课程效期表"""
content_type = models.ForeignKey(ContentType) # 关联course or degree_course
object_id = models.PositiveIntegerField() #不会在数据库生成列,只用于帮助你进行添加和查询
content_object = GenericForeignKey('content_type', 'object_id') valid_period_choices = (
(, '1天'),
(, '3天'),
(, '1周'), (, '2周'),
(, '1个月'),
(, '2个月'),
(, '3个月'),
(, '6个月'), (, '12个月'),
(, '18个月'), (, '24个月'),
)
valid_period = models.SmallIntegerField(choices=valid_period_choices)
price = models.FloatField() 使用:
# .在价格策略表中添加一条数据
# models.PricePolicy.objects.create(
# valid_period=,
# price=6.6,
# content_type=ContentType.objects.get(model='course'),
# object_id=
# ) # models.PricePolicy.objects.create(
# valid_period=,
# price=9.9,
# content_object=models.Course.objects.get(id=)
# ) # . 根据某个价格策略对象,找到他对应的表和数据,如:管理课程名称
# price = models.PricePolicy.objects.get(id=)
# print(price.content_object.name) # 自动帮你找到 # .找到某个课程关联的所有价格策略
# obj = models.Course.objects.get(id=)
# for item in obj.policy_list.all():
# print(item.id,item.valid_period,item.price)
# . 表结构
内容回顾:
. 为什么会有跨域?
浏览器具有同源策略所有才出现跨域。
同源策略:
- 开放:src
- 禁止:ajax
解决跨域:
- jsonp,在客户端动态创建一个script标签
.客户端:创建一个
<script src='http://www.jxntv.cn/data/jmd-jxtv2.html'></script>
<script>
function func(arg){
alert(arg);
}
</script>
.服务端:接收到请求并处理并返回值 "func('success')"
相当于:
<script>
func('success')
</script> PS: jsonp只能发送GET请求 - cors,设置响应响应响应响应响应头
- 简单请求
- 复杂请求
- options请求做预检
- PUT/POST.... 在django中解决方案:
- 中间件中设置响应头
- django中的一个第三方组件:cors 补充:
jQuery Ajax:
$.ajax({
...
})
原生Ajax:XMLHttpRequest对象:
var xhr = new XMLHttpRequest() xhr.onreadystatechange = function(){
if(xhr.readyState == ){
// 已经接收到全部响应数据,执行以下操作
var data = xhr.responseText;
console.log(data);
}
}; xhr.open('POST', "/test/", true); // 设置请求头
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset-UTF-8'); // 发送请求
xhr.send('n1=1;n2=2;'); . restful 规范 . 你理解的http协议? . 常见请求头
- Content-Type
- User-Agent
- referer,可以做图片防盗链。
- Host
- cookies . 常见的请求方法:
- GET/POST/DELETE/PUT/PATCH/OPTIONS . 常见的状态码:
-
- /
- /
- . 序列化 . ORM补充:
a. 需求: 只取某n列
queryset=[ {},{}]
models.User.objects.all().values( 'id','name') queryset=[ (),()]
models.User.objects.all().values_list( 'id','name') queryset=[ obj,obj]
result = models.User.objects.all().only('id','name','age')
# result = models.User.objects.all().defer('id','name','age')
for item in reuslt:
print(item.id,item.name,item.age)
b. 需求: 打印所有用户姓名以及部门名称 class depart:
title = .... class User:
name = ...
dp = FK(depart) # select * from user
# result = models.User.objects.all()
# for item in result:
# print(item.name) # select * from user left join depart on user.dp_id = depart.id
# result = models.User.objects.all().selected_related('dp')
# for item in result:
#print(item.name,item.dp.title ) 今日内容:
. 路飞学城表结构
- 课程
- 深科技 . 支付宝支付 内容详细:
. 路飞学城表结构
- 课程
- 学位课(导师、奖学金、分模块、周期)
- 专题课 (小柯,周期)
- 深科技 . 支付宝支付
a. 去支付宝申请
- 正式:营业执照
- 测试:沙箱测试环境
APPID:
买家:
nbjsag5718@sandbox.com b. 开发程序
SDK
- 官方
- github
pay.py
依赖:pip3 install pycryptodome 公钥私钥:
- 应用公钥
- 支付宝公钥
- 应用私钥
内容回顾:
. Http协议?
Http协议就是一个传输数据格式。 我原来学习django框架,从socket服务端开始学起。
自己创造了一个socket服务器来充当:网站。
浏览器当socket客户端。
更清楚的明白到底http协议是什么?
- 请求头 请求头
- 响应头 响应头 一次请求响应后,断开连接。
. 常见请求头 . 常见的请求体?
Form表单提交:
POST /index http1.\r\nhost:www.luffycity.com...\r\n\r\nusername=alex&password=&...
Ajax请求:
POST /index http1.\r\nhost:www.luffycity.com...\r\n\r\nusername=alex&password=&...
POST /index http1.\r\nhost:www.luffycity.com...\r\n\r\n{“username”:"alex","password":} 补充:django中获取请求体
- request.POST
- request.body . django请求生命周期
- wsgi, 他就是socket服务端,用于接收用户请求并将请求进行初次封装,然后将请求交给web框架(Flask、Django)
- 中间件,帮助我们对请求进行校验或在请求对象中添加其他相关数据,例如:csrf、request.session
- 路由匹配
- 视图函数,在视图函数中进行业务逻辑的处理,可能涉及到:orm、templates => 渲染
- 中间件,对响应的数据进行处理。
- wsgi,将响应的内容发送给浏览器。 . 中间件
- 5个方法
- 应用场景:
- 登录认证,不再需要在每个函数中添加装饰器
- 权限,当用户登录时候获取当前用户所有权限并放入session,然后再次访问其他页面,获取当前url并在session中进行匹配。如果没有匹配成功,则在中间件返回“无权访问”
- 跨域,
- jsonp,动态创建一个script标签。
- cors,设置响应头
应用:本地开始前后端分离的时使用。 . ORM操作
- only
- defer
- seleted_related
- prefetch_related 示例:
class Depart(models.Model): 5个部门
title = models.CharField(...) class User(models.Model): 10个用户
name = models.CharField(...)
email = models.CharField(...)
dp = models.FK(Depart) .以前的你:11次单表查询 result = User.objects.all()
for item in result:
print(item.name,item.dp.title) . seleted_related,主动做连表查询(1次链表) result = User.objects.all().seleted_related('dp')
for item in result:
print(item.name,item.dp.title) 问题:如果链表多,性能越来越差。 . prefetch_related:2次单表查询
# select * from user ;
# 通过python代码获取:dp_id = [,]
# select * from depart where id in dp_id
result = User.objects.all().prefetch_related('dp')
for item in result:
print(item.name,item.dp.title) 赠送:
数据量比较大,不会使用FK,允许出现数据冗余。 . django rest framework的作用?
快速搭建基于restful规范的接口。 . 你理解的 restful 规范?
restful是一个规范,规定API如何编写,通过他可以让我们api更加简洁可维护。
如,最直观的:
method:
- get
- post
- put
- delete 原来都是url中设置的。
除此之外:
- api
- 版本
- 名词
- 条件
- 状态码
- 返回值
- 错误信息
- hypermedia link . django rest framework组件: - 访问频率控制原理:
匿名:
1.1.1.1:[时间,时间,时间,时间,]
登录:
user:[时间,时间,时间,时间,] 默认将访问记录放在缓存中:redis/memcached
- 序列化
from rest_framework.serializers import Serializer class XX(Serializer):
pass
ser =XX(queryset,many=True) # ListSerializer对象
ser =XX(obj, many=False) # XX对象 - 列表生成式 - 根据字符串的形式,自动导入模块并使用反射找到模块中的类【参考:s9day108】。 今日内容:
. 深科技表结构
. git 内容详细:
. 深科技表结构(6表) # ######################## 深科技相关 ########################
class ArticleSource(models.Model):
"""文章来源"""
name = models.CharField(max_length=, unique=True) class Meta:
verbose_name_plural = "16. 文章来源" def __str__(self):
return self.name class Article(models.Model):
"""文章资讯"""
title = models.CharField(max_length=, unique=True, db_index=True, verbose_name="标题")
source = models.ForeignKey("ArticleSource", verbose_name="来源")
article_type_choices = ((, '资讯'), (, '视频'))
article_type = models.SmallIntegerField(choices=article_type_choices, default=)
brief = models.TextField(max_length=, verbose_name="摘要")
head_img = models.CharField(max_length=)
content = models.TextField(verbose_name="文章正文")
pub_date = models.DateTimeField(verbose_name="上架日期")
offline_date = models.DateTimeField(verbose_name="下架日期")
status_choices = ((, '在线'), (, '下线'))
status = models.SmallIntegerField(choices=status_choices, default=, verbose_name="状态")
order = models.SmallIntegerField(default=, verbose_name="权重", help_text="文章想置顶,可以把数字调大,不要超过1000")
vid = models.CharField(max_length=, verbose_name="视频VID", help_text="文章类型是视频, 则需要添加视频VID", blank=True, null=True)
comment_num = models.SmallIntegerField(default=, verbose_name="评论数")
agree_num = models.SmallIntegerField(default=, verbose_name="点赞数")
view_num = models.SmallIntegerField(default=, verbose_name="观看数")
collect_num = models.SmallIntegerField(default=, verbose_name="收藏数") # tags = models.ManyToManyField("Tags", blank=True, verbose_name="标签")
date = models.DateTimeField(auto_now_add=True, verbose_name="创建日期") position_choices = ((, '信息流'), (, 'banner大图'), (, 'banner小图'))
position = models.SmallIntegerField(choices=position_choices, default=, verbose_name="位置") #comment = GenericRelation("Comment") class Meta:
verbose_name_plural = "17. 文章" def __str__(self):
return "%s-%s" % (self.source, self.title) class Collection(models.Model):
"""收藏"""
content_type = models.ForeignKey(ContentType)
object_id = models.PositiveIntegerField()
content_object = GenericForeignKey('content_type', 'object_id') account = models.ForeignKey("Account")
date = models.DateTimeField(auto_now_add=True) class Meta:
unique_together = ('content_type', 'object_id', 'account')
verbose_name_plural = "18. 通用收藏表" class Comment(models.Model):
"""通用的评论表"""
content_type = models.ForeignKey(ContentType, blank=True, null=True, verbose_name="类型")
object_id = models.PositiveIntegerField(blank=True, null=True)
content_object = GenericForeignKey('content_type', 'object_id') p_node = models.ForeignKey("self", blank=True, null=True, verbose_name="父级评论")
content = models.TextField(max_length=)
account = models.ForeignKey("Account", verbose_name="会员名")
disagree_number = models.IntegerField(default=, verbose_name="踩")
agree_number = models.IntegerField(default=, verbose_name="赞同数")
date = models.DateTimeField(auto_now_add=True) def __str__(self):
return self.content class Meta:
verbose_name_plural = "19. 通用评论表" class Account(models.Model):
username = models.CharField("用户名", max_length=, unique=True)
password = models.CharField("密码", max_length=) class UserAuthToken(models.Model):
"""
用户Token表
"""
user = models.OneToOneField(to="Account")
token = models.CharField(max_length=, unique=True) . git
git是一个用于帮助用户实现版本控制的软件。 命令:
git init git status 查看当前文件夹的状态。
git add 文件名 对指定文件进行版本控制
git add . 对指定文件夹下的所有文件及子目录进行版本控制
git commit -m '详细的描述信息' 创建提交记录(版本) git log
git reflog git reset --hard 提交记录(版本号)