drf-day13
drf 大回顾
1 drf 入门规范 2 序列化组件---(最重要) 3 请求与响应 4 视图组件----(重要) 5 路由组件 6 认证,权限,频率---重要 7 过滤,排序,分页,全局异常 8 接口文档 9 jwt认证 10 权限:acl,rbac
混合(前后端不分离)---》图书管理系统,bbs项目
分离:后端只负责写接口
API接口
后期写的那些接口,前后端交互的媒介
请求地址
请求方式
请求参数:地址,请求体
返回数据
写了接口给谁用? 前端(web,app),提供给第三方调用
接口测试工具
发送http请求工具 get请求可以在请求体中携带数据 get请求和post请求有什么区别? 请求编码格式: urlencoded:key=value&key=value,后端django封装request.POST form-data: 数据和文件混到一起,后端django,request.FILES,request.POST json: {name:lqz,age:19},后端django,request.body,装饰器 collections创建,保存导出
restful规范
1.保证数据安全,通常采用https协议 2.接口携带api标识 3.可以对哦版本共存 4.数据就是资源,前后端交互称之为资源 5.资源的操作由请求方式决定 6.过滤、排序等可以再url上一传参的形式进行搜索 7.相应状态码 8.错误处理,返回错误信息 9.返回结果,针对不同操作,服务器向用户返回的结果应该符合以下规范 10. 需要url请求的资源需要访问资源的请求链接
序列化和反序列化
序列化:把我们的数据转化为别人能够识别的数据
反序列化:把别人提供的数据转换或者还原成我们需要的格式
Django Rest_Framework
核心思想:缩减编写api接口代码
Django REST framework是一个建立在Django基础之上的Web 应用开发框架,可以快速的开发REST API接口应用,REST framework还提供了认证、权限、限流、过滤、分页、接口文档等功能支持
提供了定义序列化器Serializer的方法,可以快速根据 Django ORM 或者其它库自动序列化/反序列化;
提供了丰富的类视图、Mixin扩展类,简化视图的编写;
丰富的定制层级:函数视图、类视图、视图集合到自动生成 API,满足各种需要;
多种身份认证和权限认证方式的支持;[jwt]
内置了限流系统;
直观的 API web 界面;
可扩展性,插件丰富CBV
》》》路由匹配成功》》》调用as_view方法》》》内部执行了as_view()方法,执行了闭包函数view,得到一个类的实例化对象
》》》在view中调用dispatch方法,先去这个类中没有找到,继续在父类view中找到dispatch方法
》》》getattr做映射》》》执行与请求方式相同的方法》》》最后将requst传入,执行该方法
APIView的执行流程
1.去除csrf认证 2.包装新的request 把数据封装在request.data reuest>query-PARAMS 其他和之前一样 3.执行认证、权限、频率 4.全局异常处理
执行流程分析
请求来了》》》匹配路由》》》路由匹配成功后,开始调用继承apiview的视图类.as_view()》》》在视图类中查找没扎到,到apiview父类中查找,apiview中的as_view调用父类view中的as_view方法,将返回值赋值给apiview中的变量view,所以view就等于父类view中的闭包函数view,而api中的as_view本质是去除csrf认证》》》调用dispatch方法,在视图类中没有
,在apiview中查找到后,dispatch包装一个全新的request赋值给原来的self.request》》》然后执行里面的三大认证》》》反射找到请求方式相同的方法,最后执行此方法,把request传到这个方法中
序列化组件
序列化组件的作用
1.可以序列化 2.可以反序列化 3.反序列化的校验:字段自己,局部钩子,全局钩子
快速使用
1.创建一个py文件,写一个类,继承Serializer 2.在类中写字段 3.在视图类中:实例化得到序列化类的对象:多条,many 4.序列化:序列化类的对象.data retrun Response(ser.data)
常用字段
跟models中之前学过的有对应关系
ListField DictField 》》》序列化和反序列化都会用
字段参数
限制反序列化校验字段自己规则的
read_only write_only:控制字段只做序列化或反序列化的,如果不写就是
使用序列化类做反序列化
新增 ser=BookSerializer(data=request.data) ser.is_valid(raise_exception=True)--->只要校验不通过,直接抛异常 ser.save() # 继承Serializer,需要在序列化类中重写create方法,完成新增 序列化类中重写create方法 def create(self, validated_data): # validated_data 前端传入,校验过后的数据 # 新增一个对象 return 新增的对象 # 后续再视图类中只要调用ser.data,这里必须返回 修改 ser=BookSerializer(instance=要修改的对象,data=request.data) ser.is_valid(raise_exception=True)--->只要校验不通过,直接抛异常 ser.save() # 继承Serializer,需要在序列化类中重写update方法,完成修改 序列化类中重写update def update(self, instance, validated_data): # instance 要修改的对象,哪里来的?BookSerializer(instance=要修改的对象的id,data=request.data) # validated_data:校验过后数据 res=Book.objects.filter(pk=instance).update(**validated_data) return res # 返回的res最后干啥了?只要在 视图类中 调用ser.data,他会根据这个返回值做序列化
反序列化校验
1.字段自己 2.局部钩子--》序列化类中写 validate_字段名 传参数 3.全局钩子---》序列化类中写 validate 传参数,字典 登录接口
定制返回格式
source:1 改名 2 跨表查 3 拿表模型中的方法 SerializerMethodField:在序列化类中写 publish=serializers.SerializerMethodField(read_only) 配合一个 get_username(self,obj)的方法,返回什么,这个字段就是什么 在表模型中写:方法 publish=serializers.DictField() 只能做序列化用了,反序列化得单独用---》需要使用read_only和write_only控制
ModelSerializer使用
class Meta: model=表名 fields=[需要序列化或反序列化的字段,表中没有也要写] extra_kwargs={} # 传入字段参数 重写字段 大部分情况下不需要写create和update了 局部,全局钩子跟之前一模一样
视图组件
两个视图基类
APIVIew 类属性 renderer_classes = api_settings.DEFAULT_RENDERER_CLASSES parser_classes = api_settings.DEFAULT_PARSER_CLASSES authentication_classes = api_settings.DEFAULT_AUTHENTICATION_CLASSES throttle_classes = api_settings.DEFAULT_THROTTLE_CLASSES permission_classes = api_settings.DEFAULT_PERMISSION_CLASSES GenericAPIView:要使用序列化类,数据库打交道,就可以继承它 queryset = None serializer_class = None lookup_field = 'pk' filter_backends = api_settings.DEFAULT_FILTER_BACKENDS pagination_class = api_settings.DEFAULT_PAGINATION_CLASS get_queryset(self) #获取所有要序列化的数据,在里面拿到qs对象后要 .all() get_object # 获取单个对象 get_serializer()--->内部调用了get_serializer_class--》最终返回序列化类的对象,传入要传的参数---》instance ,data many filter_queryset---》给ListModelMixin用了--》把配置的filter_backends 依次执行完成过滤
五个扩展类,需要搭配genericAPIView
ListModelMixin, CreateModelMixin, UpdateModelMixin, DestroyModelMixin, RetrieveModelMixin 一个视图类中写四个接口--》必须借助于ViewSetMixin class BookView(ViewSetMixin,GenericAPIView,ListModelMixin,CreateModelMixin,RetrieveModelMixin,DestroyModelMixin): queryset = None serializer_class = None
九个视图子类
ListAPIView,
CreateAPIView
RetrieveAPIView,
DestroyAPIView,
UpdateAPIView
其余四个都是上面五个的组合
视图集
-ModelViewSet:重写方法实现你想要的功能 -ReadOnlyModelViewSet -ViewSetMixin:路由写法变了 -ViewSet:ViewSetMixin+APIView -GenericViewSet:ViewSetMixin+GenericAPIView
-请求源码:request对象 -request.data -request.query_params -跟之前一样 -request._request -__getattr__ -请求能解析编码格式:parser_classes -局部使用 -全局使用
响应
响应Response 源码 -data:响应体的内容,序列化后的数据给了他 -headers:响应头 django原生响应头 响应对象['xx']=xxx -status:响应状态码 -响应编码格式--》浏览器,postman,看到的样子 -局部和全局配置
路由组件
1 只要继承ViewSetMixin及其子类,路由写法就变了 -方式一:映射方式 视图类.as_view({'get':'lqz'}) -方式二:自动生成 -SimpleRouter DefaultRouter
2 action装饰器
参数:methods detai
1 写个类,继承BaseAuthentication 2 重写autenticate 3 取出用户传入的 token ---》通过token能知道是谁 4 认证通过取出用户,认证失败,抛出异常 5 return 查到的对象,token---》后续再request.user中就是当时返回的第一个值 6 视图类中配置 7 全局配置
权限类
1 写个类,继承BasePermission 2 has_permission 3 判断用户的权限 acl 权限,取出当前用户所有权限,判断当次请求是否在权限中 rbac,根据当前用户取出所有角色,通过角色取出所有权限,去个重,判断是否在权限中 4 有权限返回True,没有返回False 5 视图类中配置 6 全局配置
频率类
1 写个类,继承SimpleRatethrottle 2 重写get_cache_key 返回值 唯一的 ip,userid 3 类属性 scope='字符串' 4 配置文件配置 'DEFAULT_THROTTLE_RATES': { '字符串': '3/m', }, 5 视图类中配置 6 全局配置
为什么我们写了 权限类,配置行,它就会执行权限控制?
-APIView 的dispatch中执行了3大认证---》 def dispatch(self, request, *args, **kwargs): self.initial(request, *args, **kwargs) # 三大认证 - self.initial 需要从根上 def initial(self, request, *args, **kwargs): self.perform_authentication(request) self.check_permissions(request) # 权限类的执行位置 self.check_throttles(request) -self.check_permissions(request) def check_permissions(self, request): for permission in self.get_permissions(): # 你配置在视图类上一个个权限类的对象列表 [权限对象1,权限对象2] if not permission.has_permission(request, self): # self,是视图类的对象,因为在APIView中 self.permission_denied( request, message=getattr(permission, 'message', None), code=getattr(permission, 'code', None) ) - def get_permissions(self): return [permission() for permission in self.permission_classes]
认证类源码
-APIView 的dispatch中执行了3大认证---》 def dispatch(self, request, *args, **kwargs): self.initial(request, *args, **kwargs) # 三大认证 - self.initial 需要从根上 def initial(self, request, *args, **kwargs): self.perform_authentication(request)# 认证类的执行位置 self.check_permissions(request) self.check_throttles(request) - def perform_authentication(self, request): request.user -去Request类中找user---》方法包装成了数据属性 @property def user(self): if not hasattr(self, '_user'): with wrap_attributeerrors(): self._authenticate() return self._user -去Request类中找self._authenticate() def _authenticate(self): for authenticator in self.authenticators: # 配置在视图类上一个个认证类的对象列表 try: # 调用认证类对象的authenticate方法,传入 self,是request对象 user_auth_tuple = authenticator.authenticate(self) # 当前登录用户,token except exceptions.APIException: self._not_authenticated() raise if user_auth_tuple is not None: self._authenticator = authenticator #self就是request对象,后续 request.user就是认证类返回的第一个参数 self.user, self.auth = user_auth_tuple # 解压赋值 return self._not_authenticated() -认证类可以配置多个,但是如果有一个返回了,后续的就不走了 -self.authenticators 是request对象的属性,是在Request实例化的时候传入的,它什么时候实例化的,包装新的Reqeust时传入的---》APIView的dispatch--》
http与https之间的区别
1、HTTPS协议需要到CA申请证书,一般免费的证书比较少,因而需要一定费用。 2、HTTP是超文本传输协议,信息是明文传输,HTTPS则是具有安全性的SSL加密传输协议。 3、HTTP和HTTPS使用的是完全不同的链接方式,用的端口也不一样,前者是80端口,后者是443端口。 4、HTTP的链接很简单,是无状态的;HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,比HTTP协议安全。
GET 和POST请求方法的区别
1、post请求更安全;post请求不会作为url的一部分,不会被缓存、保存在服务器日志、以及浏览器浏览记录中,get请求的是静态资源,则会缓存,如果是数据,则不会缓存。 2、post请求发送的数据更大,get请求有url长度限制。 3、post请求能发送更多的数据类型,get请求只能发送ASCII字符。 4、传参方式不同。 5、get产生一个TCP数据包;post产生两个
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY