1、Django请求声明周期
- (1)执行遵循wsgi协议的模块(socket服务端)
from wsgiref.simple_server import make_server
def RunServer(environ, start_response):
start_response('200 OK', [('Content-Type', 'text/html')])
return [bytes('<h1>Hello, web!</h1>', encoding='utf-8'), ]
if __name__ == '__main__':
httpd = make_server('', 8000, RunServer)
print("Serving HTTP on port 8000...")
httpd.serve_forever()
自定义Web框架
- (2)中间件(路由匹配)
- (3)视图函数(业务处理:ORM、模板渲染)
- (4)Wsgi做返回
- (5)流程图如下:
2、什么是wsgi
- (1)web服务网关接口
- (2)实现该协议的模块:
-wsgiref
-werkzurg
-uwsgi
3、视图
- (1)FBV
url - 函数 - (2)CBV
url - view
4、django rest framework
5、restful规范
什么是接口?
-
(1)根据method不同,进行不同操作
GET/POST/PUT/DELETE/PATH -
(2)面向资源编程
http://www.gkate.com/article -
(3)体现版本
http://www.gkate.com/v2/article
http://www.gkate.com/v3/article -
(4)体现API
http://v2.gkate.com/api/article
http://api.gkate.com/article -
(5)Https
https://v2.gkate.com/api/article -
(6)响应式设置状态码
200 – 成功
300 – 302, 302重定向
400 – 404页面找不到
500 --代码错误
return HttpResponse(‘afad’,status = 300) -
(8)返回值
http://v2.gkate.com/api/article
GET所有列表:
{
code: 10000,
data: [
{'id':1,'title':'三体'},
{'id':1,'title':'流浪'},
{'id':1,'title':'阿丽塔'},
]
}
POST:返回新增的数据
{'id':1,'title':'Twiss'},
{'id':2,'title':'Iran'}
GET:获得单条数据
PUT:更新
PATCH:拒不更新
DELETE:删除
- (9)返回错误信息
{
code:10001,
error:'XX错误信息'
}
- (10)Hypermedia API
ret = {
code: 1000,
data:{
id:1,
name:'小强',
depart_id:http://www.luffycity.com/api/v1/depart/8/
}
}
6、django rest framework框架(10)
-
(1) 路由
- 可以通过as_view传参数,根据请求方式不同执行相应的方法
- 可以在url设置一个结尾,类似 .json
-
(2) 视图
- 帮助开发者提供一些类,并在类中提供多个方法以供我们使用
-
(3) 版本
- 在URL中设置version参数,用户请求时传入参数,在request.version中获取版本,根据版本不同做不同处理
-
(4) 认证
- 写一个类并注册到认证类,在类的authicate方法中编写认证逻辑
- 认证成功(user,auth)
- raise AuthicateFaild(…)
- None
- 写一个类并注册到认证类,在类的authicate方法中编写认证逻辑
-
(5) 权限
- 写一个类并注册到权限类,在类的has_permission方法中编写认证逻辑
- True
- False
- 写一个类并注册到权限类,在类的has_permission方法中编写认证逻辑
-
(6) 访问频率限制
- 写一个类并注册到频率类,在类的allow_request/wait方法中编写认证逻辑
- allow_request
- True
- False 如果返回FALSE,执行wait
- allow_request
- 写一个类并注册到频率类,在类的allow_request/wait方法中编写认证逻辑
面试题:你的写的类都继承过哪些类?
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):
- (7) 解析器
- 根据ContentType请求头,选择不同解析器对请求体的数据进行解析
- (8) 序列化
- 对queryset序列化以及对请求数据格式校验
- (9) 分页
- 对数据库中获取的数据进行分页处理:SQL->limit offset
- 根据页码:http://www.gkate.cn/api/v1/article/?page=1&size=10
- 根据索引: http://www.gkate.cn/api/v1/article/?offset=60&limit=10
- 根据加密: http://www.gkate.cn/api/v1/article/?page=erd=8
- 页码越大速度越慢,为什么如何解决?
- 原因:页码越大向后扫描的行数越多,因为每次都是从0开始扫描
- 解决:(1)记录当前页数据ID最大值和最小值,再次分页时根据ID现行筛选,然后在分页 (2)限制显示的页数
- 对数据库中获取的数据进行分页处理:SQL->limit offset
- (10) 渲染器
- 根据URL传入的后缀,决定在数据如何渲染到页面上
7、理解Http协议
- 建立在TCP协议之上
- 一次请求一次响应然后断开连接(无状态、短连接)
- 请求响应
发送:请求头\r\n\r\n请求体
响应:响应头\r\n\r\n响应体
8、Django中间件是什么?
process_request
process_view
process_response
process_exception
process_render_template
9、中间件做过什么?
- (1)内置
- csrf
- session
- (2)自定义
- 登录认证
- 权限
- cors
10、中间件中有多少个方法?
5个
process_request
process_view
process_response
process_exception
process_render_template
11、视图常见继承
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 # *
12、如何实现的访问频率控制?
匿名用户:无法控制,因为用户可以换代理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],
}
登录用户:如果有很多账号,也无法限制
{
Twiss:[1521223123.232, 1521223122.232, 1521223121.232],
Gkate:[1521223123.232, 1521223122.232, 1521223121.232],
}
参考源码:from rest_framework.throttling import SimpleRateThrottle
13、常见的请求头
- Content-Type
- User-Agent
- refere,可以用作图片防盗链
- Host
- Cookies
14、常见的请求方法
- GET
- POST
- DELETE
- PUT
- PATCH
- OPTIONS
15、常见的状态码
- 200
- 301/ 302
- 403/ 404
- 500
16、为什么会有跨域?
16.1 浏览器具有同源策略所有才出现跨域。
16.2同源策略:
- 开放:src
- 禁止:ajax
16.3解决跨域:
- jsonp,在客户端动态创建一个script标签
(1)客户端:创建一个
<script src='http://www.jxntv.cn/data/jmd-jxtv2.html'></script>
<script>
function func(arg){
alert(arg);
}
</script>
(2)服务端:接收到请求并处理并返回值 “func(‘success’)”
相当于:
<script>
func('success')
</script>
PS: jsonp只能发送GET请求
- cors,设置响应响应响应响应响应头
- 简单请求
- 复杂请求
- options请求做预检
- PUT/POST…
16.4在django中解决方案:
- 中间件中设置响应头
- django中的一个第三方组件:cors
16.5 JQuery Ajax
jQuery Ajax:
$.ajax({
...
})
原生Ajax:XMLHttpRequest对象:
var xhr = new XMLHttpRequest()
xhr.onreadystatechange = function(){
if(xhr.readyState == 4){
// 已经接收到全部响应数据,执行以下操作
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;');
17、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)
1、# select * from user
result = models.User.objects.all()
for item in result:
print(item.name)
2、# 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 )
问题:如果链表多,性能越来越差。
3、#prefetch_related:2次单表查询(支持many to many)
# select * from user ;
# 通过python代码获取:dp_id = [1,2]
# 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)
18、Django rest framework的作用
快速搭建基于restful规范的接口