一、Django的请求生命周期
1.wsgi,它就是socket的服务端,用于接收用户请求并将请求进行初次封装,然后讲求交给(Flask,Django)进行二次封装。
2.中间件,帮助我们对请求进行校验或在请求对象中添加其他相关数据,例如:csrf、request.session
3.路由匹配
4.视图函数,在视图函数中进行业务逻辑的处理,可能涉及到:ORM、templates ==>>渲染
5.中间件,对响应的数据进行处理。
6.wsgi,将响应的内容发给浏览器。
Django的流程图:
二、什么是wsgi?
wsgi是web服务网管接口
实现该协议的模块:
wsgiref、werkzurg、uwsgi
三、什么是HTTP协议?
HTTP协议就是一种传输数据的格式,是基于TCP的之上的。原来学习django框架,是从socket服务端开始学起。
自己创造一个socket服务器来充当网站,浏览器充当socket客户端。
更能够明白http协议到底是什么:
----- 请求头 请求体
----- 响应头 响应体
一次请求响应后,断开链接。(无状态,短连接)
四、常见的请求头
- Content-Type
- User-Agent: 值得不同,返回不同的页面。(根据设备)
- referer: 可以做图片防盗链。
- Host: 当前域名
- cookies: 携带在请求头里面
五、常见的请求体?
Form表单提交:
POST /index http1.1\r\nhost:www.luffycity.com...\r\n\r\nusername=alex&password=123&...
Ajax请求:
POST /index http1.1\r\nhost:www.luffycity.com...\r\n\r\nusername=alex&password=123&...
POST /index http1.1\r\nhost:www.luffycity.com...\r\n\r\n{“username”:"alex","password":123}
补充:django中获取请求体
- request.POST 只能获取这种可是的(nusername=alex&password=123)
- request.body 能够获得 ({“username”:"alex","password":123})
常见的请求方法:
GET/POST/DELETE/PUT/PATCH/OPTIONS
六、中间件
中间件有五种方法:
process_request(self,request)
process_view(self, request, callback, callback_args, callback_kwargs)
process_template_response(self,request,response)
process_exception(self, request, exception)
process_response(self, request, response
中间件的应用场景:
1.登录认证,不再需要在每个函数中添加装饰器。
2.权限,当用户登录的时候获得当前用户的所有权限并放入session,然后再次访问其他页面,获取当前url并在session中进行匹配。如果没有匹配成功,则在中间件返回“无权访问”
3.跨域
4.使用中间件做过什么?
(1)内置 csrf sesson
(2)自定义 登录认证 权限 cors
七、为什么会有跨域?
浏览器具有同源策略才出现跨域。
同源策略:
开放:src
禁止:ajax
解决跨域的两种方法:
1、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>
必须与上边一致,而且jsonp只能发送GET请求
2、cors:设置响应头
(1)简单请求
(2)复杂请求
options 请求做预检
PUT/POST
应用:本地测试前后端分离时使用。
在Django中的解决方案:
1、中间件中设置响应头
2、Django中的一个第三方组件:cors
补充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;');
八、视图
在本质的上FBV和CBV是一样的
区别:
FBV:url----->函数(自己定义)
CBV: url----->view (继承的类)
继承的类:
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):
九、restful规范
restful是一个规范,规定API如何编写,通过它可以让我们api更加简洁方便维护。
例如,最直观的:
method: get/post/put/delete
原来都是在url中设置的。
除此之外还有:
(1) api
(2)版本
(3)名词(面向资源编程)
(4)条件
(5)响应式设置状态码
(6)返回值
GET: 所有列表
{
code: 10000,
data: [
{'id':1,'title':'xx'},
{'id':1,'title':'yy'},
{'id':1,'title':'zzz'},
]
}
POST: 返回新增的数据
{'id':1,'title':'xx'}
https://www.luffycity.com/api/v2/salary/1/
GET: 获取单条数据
{'id':1,'title':'xx'}
PUT:更新
{'id':1,'title':'xx'}
PATCH: 局部更新
{'id':1,'title':'xx'}
DELETE:删除
(7)错误信息
(8)hypermedia link
什么是接口?
URL
约束:约束继承(实现)了它的类中必须含有的方法
十、django rest framework 框架
作用:快速搭建基于restful规定的接口
1、视图
2、视图
3、版本
4、认证
5、权限
6、访问频率的限制
- 访问频率控制原理:
匿名:
1.1.1.1:[时间,时间,时间,时间,]
登录:
user:[时间,时间,时间,时间,]
默认将访问记录放在缓存中:redis/memcached
7、解析器
8、序列化
from rest_framework.serializers import Serializer
class XX(Serializer):
pass
ser =XX(queryset,many=True) # ListSerializer对象
ser =XX(obj, many=False) # XX对象
- 列表生成式
- 根据字符串的形式,自动导入模块并使用反射找到模块中的类【参考:s9day108】。
9、分页
10、渲染器
十一、ORM的补充
a. 需求: 只取某n列
queryset=[ {},{}]
models.User.objects.all().values( 'id','name')
queryset=[ (),()]
models.User.objects.all().values_list( 'id','name')
queryset=[ obj,obj]
b. - only
result = models.User.objects.all().only('id','name','age')
c. - defer
# result = models.User.objects.all().defer('id','name','age')
for item in reuslt:
print(item.id,item.name,item.age)
示例:
class Depart(models.Model): 5个部门
title = models.CharField(...)
class User(models.Model): 10个用户
name = models.CharField(...)
email = models.CharField(...)
dp = models.FK(Depart)
1.之前:11次单表查询
result = User.objects.all()
for item in result:
print(item.name,item.dp.title)
2. seleted_related,主动做连表查询(1次链表)
result = User.objects.all().seleted_related('dp')
for item in result:
print(item.name,item.dp.title)
问题:如果链表多,性能越来越差。
3. prefetch_related:2次单表查询
# 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)
注:数据量比较大,不会使用FK,允许出现数据冗余。