Django框架之drf

一、反序列化类校验部分源码解析

反序列化校验什么时候开始执行校验

剖析流程一:在视图中使用反序列化器实例化的对象调用is_valid()的时候就会进行校验,通贩校验返回True,反之False

    class BookView(APIView):
# 新增
def post(self, request):
ser_obj = BookSerializer(data=request.data)
# 触发反序列化类校验
if ser_obj.is_valid():
ser_obj.save()
return Response({'code': 100, 'msg': '新增图书成功', 'result': ser_obj.data})
return Response({'code': 101, 'msg': ser_obj.errors})

解析流程二:入口:ser.is_valid() 是序列化类的对象,假设序列化类是BookSerializer---》is_valid---》找不到,在父类中找到BaseSerializer

def is_valid(self, *, raise_exception=False):
if not hasattr(self, '_validated_data'):
try:
# self序列化类的对象,属性中没有_validated_data,一定会走这句【核心】
self._validated_data = self.run_validation(self.initial_data)
except ValidationError as exc:
self._validated_data = {}
self._errors = exc.detail
else:
self._errors = {} if self._errors and raise_exception:
raise ValidationError(self.errors) return not bool(self._errors)

解析流程三:self._validated_data = self.run_validation(self.initial_data) 核心--》self序列化类的对象

  • 切记一定不要按住ctrl键点击

  • 真正的执行顺序是,从下往上找,找不到,再往上

  • 最终从Serializer类中找到了run_validation,而不是Field中的run_validation

def run_validation(self, data=empty):
# 字段自己的,validates方法
(is_empty_value, data) = self.validate_empty_values(data)
if is_empty_value:
return data
# 局部钩子----【局部钩子】
value = self.to_internal_value(data)
try: self.run_validators(value)
# 全局钩子--》如果在BookSerializer中写了validate,优先走它,非常简单
value = self.validate(value) except (ValidationError, DjangoValidationError) as exc:
raise ValidationError(detail=as_serializer_error(exc)) return value # 局部钩子 self.to_internal_value(data)---》self是BookSerializer的对象,从根上找
def to_internal_value(self, data):
ret = OrderedDict()
errors = OrderedDict()
fields = self._writable_fields
# fields写在序列化类中一个个字段类的对象
for field in fields:
# self BookSerializer的对象,反射validate_name
validate_method = getattr(self, 'validate_' + field.field_name, None)
try:
# 在执行BookSerializer类中的validate_name方法,传入了要校验的数据
validated_value = validate_method(validated_value)
except ValidationError as exc:
errors[field.field_name] = exc.detail else:
set_value(ret, field.source_attrs, validated_value) if errors:
raise ValidationError(errors) return ret

二、断言

​ 用于判断一个表达式,在表达式的条件为False时会触发异常,反之正常往下执行代码,断言可以在条件不满足的时候主动抛出异常

关键词:assert

用法:

name = 'kangkang'

# 如果name不等于'kangkang',那么将会直接抛出异常代码
assert name== 'kangkang'
print('正确,正常执行')

三、drf之请求

1、Request能够解析的前端传入编码格式

drf为我们提供了三种编码格式分别是:

  • 第一种:rest_framework.parsers.JSONParser

    • 对应前端的:json格式数据
  • 第二种:rest_framework.parsers.FormParser

    • 对应前端的:form-data格式数据
  • 第三种:rest_framework.parsers.MultiPartParser

    • 对应前端的:urlencode

配置请求编码的方法:

​ 这三种编码在默认都是开启的,配置的方法有两种:

  • 在视图类中配置(局部)

  • django的settings.py文件中配置(全局)

导入模块:(三种请求模块)
from rest_framework.parsers import JSONParser, FormParser, MultiPartParser # 方式一:在视图类中配置(只会影响该视图类下的方法)
class BookView(APIView):
parser_classes = ['JSONParser', 'FormParser', 'MultiPartParser'] # 方式二:django的settings.py中配置(影响全局)
REST_FRAMEWORK = {
'DEFAULT_PARSER_CLASSES': [
'rest_framework.parsers.JSONParser',
'rest_framework.parsers.FormParser',
'rest_framework.parsers.MultiPartParser',
],
} # 方式三:全局配了1个,某个视图类想要3个,怎么配?
-只需要在视图类,配置3个即可
-因为:先从视图类自身找,找不到,去项目的drf配置中找,再找不到,去drf默认的配置找

2、Request类中的属性和方法

# 该节在上述中已经讲过,此处只做总结
继承APIView的视图类中的request是经过drf处理后的requset,该类不仅包含了django原生的request的所有方法,还新增了以下功能
1、request.data # (所有请求数据都可以在这里取出,升级版的request.body)
2、__getattr__ # 该魔法方法是新的request中的方法,调用不存在的方法会回到老的requert中去找
3、query_params # 和老的request.get用法一致

四、drf之响应

1、Response能够响应的编码格式

​ drf是django的一个app,所以需要在django的settings.py中进行配置,否则浏览器将无法正常访问

​ drf的响应,使用浏览器和postman访问同一个接口,返回的格式是不一样的,如果是浏览器将会返回的格式好看一点,postman直接返回数据本身。响应的格式共有两种,配置方法类似于请求的配置方法

配置方法:

导入模块:(两种响应方式模块)
from rest_framework.renderers import JSONRenderer,BrowsableAPIRenderer # 方式一:视图类中配置(局部配置,不会影响全局)
class BookView(APIView):
renderer_classes=[JSONRenderer,] # 方式二、django中配置项目文件(全局配置,局部配置的话优先采用局部)
REST_FRAMEWORK = {
'DEFAULT_RENDERER_CLASSES': [
'rest_framework.renderers.JSONRenderer',
'rest_framework.renderers.BrowsableAPIRenderer',
],
} # 方式三:使用顺序(一般就用内置的即可)
优先使用视图类中的配置,其次使用项目配置文件中的配置,最后使用内置的

2、Response的源码属性或方法

Response源码分析

# 导入Response模块:
from rest_framework.response import Response # Response init可以传的参数
def __init__(self,
data=None,
status=None,
template_name=None,
headers=None,
exception=False,
content_type=None) # data:
之前咱们写的ser.data,可以是字典或列表,字符串---》序列化后返回给前端---》前端在响应体中看到的就是这个 # status:
http响应的状态码,默认是200,可以通过导入模块进行修改
-from rest_framework.status import HTTP_200_OK
-Response('xxx',status=status.HTTP_200_OK) # template_name:
解即可,修改响应模板的样子,BrowsableAPIRenderer定死的样子,后期公司可以自己定制 # headers:
响应头,http响应的响应头
原生django,响应头中添加数据
obj = HttpResponse('dddd')
obj['xxc'] = 'yyc'
return obj # content_type :
响应编码格式,一般不动

五、视图组件介绍及两个视图基类

APIView是drf提供的视图类中最顶层的视图基类

1、APIView与View区别

  • 传入到视图方法中的是REST framework的Request对象,而不是Django的HttpRequeset对象
  • 视图方法可以返回REST framework的Response对象
  • 任何APIException异常都会被捕获到,并且处理成合适的响应信息
  • 在进行dispatch()分发前,会对请求进行身份认证、权限检查、流量控制(执行三大认证)

2、视图基类

APIVIew
-类属性:
renderer_classes # 响应格式
parser_classes # 能够解析的请求格式
authentication_classes #认证类
throttle_classes # 频率类
permission_classes # 权限类

六、基于APIView+ModelSerializer+Resposne写5个接口

1、视图类

from rest_framework.views import APIView
from rest_framework.response import Response
from .serializer import BookSerializer
from .models import Book class BookView(APIView):
# 查询多条
def get(self, request):
book_obj_all = Book.objects.all()
serializer_obj = BookSerializer(instance=book_obj_all, many=True)
return Response(serializer_obj.data) # 新增
def post(self, request):
res_obj = BookSerializer(data=request.data)
res_obj.is_valid(raise_exception=True)
res_obj.save()
return Response({'cede': 100, 'msg': '新增成功', 'result': res_obj.data}) class BookDetailView(APIView):
# 查询单条
def get(self, request, *args, **kwargs):
book_obj = Book.objects.filter(**kwargs).first()
serializer_obj = BookSerializer(instance=book_obj)
return Response(serializer_obj.data) # 修改
def put(self, request, *args, **kwargs):
target_book_obj = Book.objects.filter(**kwargs).first()
serializer_obj = BookSerializer(instance=target_book_obj, data=request.data)
serializer_obj.is_valid(raise_exception=True)
serializer_obj.save()
return Response({'code': 100, 'msg': '修改成功', 'result': serializer_obj.data}) # 删除
def delete(self, request, *args, **kwargs):
Book.objects.filter(**kwargs).delete()
return Response({'code': 100, 'msg': '删除成功'})

2、序列化类

from rest_framework import serializers
from rest_framework.exceptions import ValidationError
from .models import Book # 序列化类
class BookSerializer(serializers.ModelSerializer):
class Meta:
# 绑定的表
model = Book
# 序列化的字段
fields = ['pk', 'name', 'price', 'authorList', 'publishDetail', 'author', 'publish'] # 字段校验条件
extra_kwargs = {
'name': {'max_length': 32},
'authorList': {'read_only': True},
'publishDetail': {'read_only': True},
'author': {'write_only': True},
'publish': {'write_only': True}
} # 全局钩子
def validate(self, attrs):
if int(attrs.get('price')) > 100:
raise ValidationError('价格不能超过100元')
return attrs

3、路由

from django.contrib import admin
from django.urls import path
from app01 import views urlpatterns = [
path('admin/', admin.site.urls),
# 查询多条、新增接口
path('book/', views.BookView.as_view()),
# 查询单条、修改、删除接口
path('book/<int:pk>/', views.BookDetailView.as_view())
]

4、模型类

from django.db import models

class Book(models.Model):
name = models.CharField(max_length=32)
price = models.CharField(max_length=32) author = models.ManyToManyField(to='Author') # 外键字段数据序列化功能函数
def authorList(self):
author_data_list = [{'name': author_obj.name,
'phone': author_obj.phone,
'age': author_obj.authorinfo.age,
'address': author_obj.authorinfo.gender
} for author_obj in self.author.all()]
return author_data_list publish = models.ForeignKey(to='Publish', on_delete=models.CASCADE, null=True) # 外键字段数据序列化功能函数
def publishDetail(self):
return {'name': self.publish.name, 'address': self.publish.address} class Author(models.Model):
name = models.CharField(max_length=32)
phone = models.CharField(max_length=11) authorinfo = models.OneToOneField(to='AuthorInfo', on_delete=models.CASCADE, null=True) class AuthorInfo(models.Model):
age = models.CharField(max_length=8)
gender = models.CharField(max_length=8) class Publish(models.Model):
name = models.CharField(max_length=32)
address = models.CharField(max_length=32)

七、基于GenericAPIView+5个视图扩展类

1、视图类

from rest_framework.generics import GenericAPIView
from rest_framework.mixins import ListModelMixin, CreateModelMixin, UpdateModelMixin, DestroyModelMixin, \
RetrieveModelMixin
from .serializer import BookSerializer
from .models import Book class BookView(GenericAPIView, ListModelMixin, CreateModelMixin):
queryset = Book.objects.all()
serializer_class = BookSerializer # 查询多条
def get(self, request):
return self.list(request) # 新增
def post(self, request):
return self.create(request) class BookDetailView(GenericAPIView,
RetrieveModelMixin,
DestroyModelMixin,
UpdateModelMixin):
queryset = Book.objects.all()
serializer_class = BookSerializer # 查询单条
def get(self, request, *args, **kwargs):
return self.retrieve(request, *args, **kwargs) # 修改
def put(self, request, *args, **kwargs):
return self.update(request, *args, **kwargs) # 删除
def delete(self, request, *args, **kwargs):
return self.delete(request, *args, **kwargs)

2、序列化类

from rest_framework import serializers
from rest_framework.exceptions import ValidationError
from .models import Book # 序列化类
class BookSerializer(serializers.ModelSerializer):
class Meta:
# 绑定的表
model = Book
# 序列化的字段
fields = ['pk', 'name', 'price', 'authorList', 'publishDetail', 'author', 'publish'] # 字段校验条件
extra_kwargs = {
'name': {'max_length': 32},
'authorList': {'read_only': True},
'publishDetail': {'read_only': True},
'author': {'write_only': True},
'publish': {'write_only': True}
} # 全局钩子
def validate(self, attrs):
if int(attrs.get('price')) > 100:
raise ValidationError('价格不能超过100元')
return attrs

3、路由

from django.contrib import admin
from django.urls import path
from app01 import views urlpatterns = [
path('admin/', admin.site.urls),
# 查询多条、新增接口
path('book/', views.BookView.as_view()),
# 查询单条、修改、删除接口
path('book/<int:pk>/', views.BookDetailView.as_view())
]

4、模型类

from django.db import models

class Book(models.Model):
name = models.CharField(max_length=32)
price = models.CharField(max_length=32) author = models.ManyToManyField(to='Author') # 外键字段数据序列化功能函数
def authorList(self):
author_data_list = [{'name': author_obj.name,
'phone': author_obj.phone,
'age': author_obj.authorinfo.age,
'address': author_obj.authorinfo.gender
} for author_obj in self.author.all()]
return author_data_list publish = models.ForeignKey(to='Publish', on_delete=models.CASCADE, null=True) # 外键字段数据序列化功能函数
def publishDetail(self):
return {'name': self.publish.name, 'address': self.publish.address} class Author(models.Model):
name = models.CharField(max_length=32)
phone = models.CharField(max_length=11) authorinfo = models.OneToOneField(to='AuthorInfo', on_delete=models.CASCADE, null=True) class AuthorInfo(models.Model):
age = models.CharField(max_length=8)
gender = models.CharField(max_length=8) class Publish(models.Model):
name = models.CharField(max_length=32)
address = models.CharField(max_length=32)

Django框架之drf:5、反序列化器校验部分源码分析、断言、drf之请求与响应、视图组件介绍及两个视图基类、代码部分实战的更多相关文章

  1. DRF框架(五)——context传参,二次封装Response类,两个视图基类(APIView/GenericAPIView),视图扩展类(mixins),子类视图(工具视图),视图集(viewsets),工具视图集

    复习 1.整体修改与局部修改 # 序列化get (给前端传递参数) #查询 ser_obj = ModelSerializer(model_obj) #只传递一个参数,默认是instance的参数,查 ...

  2. DRF框架(一)——restful接口规范、基于规范下使用原生django接口查询和增加、原生Django CBV请求生命周期源码分析、drf请求生命周期源码分析、请求模块request、渲染模块render

    DRF框架    全称:django-rest framework 知识点 1.接口:什么是接口.restful接口规范 2.CBV生命周期源码 - 基于restful规范下的CBV接口 3.请求组件 ...

  3. drf 认证校验及源码分析

    认证校验 认证校验是十分重要的,如用户如果不登陆就不能访问某些接口. 再比如用户不登陆就不能够对一个接口做哪些操作. drf中认证的写法流程如下: 1.写一个类,继承BaseAuthenticatio ...

  4. drf的基本使用、APIView源码分析和CBV源码拓展

    cbv源码拓展 扩展,如果我在Book视图类中重写dispatch方法 -可以实现,在get,post方法执行之前或者之后执行代码,完成类似装饰器的效果 def dispatch(self, requ ...

  5. drf复习(一)--原生djangoCBV请求生命周期源码分析、drf自定义配置文件、drf请求生命周期dispatch源码分析

    admin后台注册model  一.原生djangoCBV请求生命周期源码分析 原生view的源码路径(django/views/generic/base.py) 1.从urls.py中as_view ...

  6. okhttp框架源码分析从同步&异步请求使用开始

    对于okhttp在如今项目中的普及程度已经不言而喻啦,基本上如今网络请求都会基于它去进行封装,而非前几年用Android的网络框架HttpURLConnection和Apache HttpClient ...

  7. sentinel流控规则校验之源码分析

    前言: 上节给大家把sentinel流控整个执行大致过了,但涉及到最核心的流控算法还没有讲,先提前说明一下 sentinel用的流控算法是令牌桶算法,参考了Guava的RateLimiter,有读过R ...

  8. *CI框架装载器Loader.php源码分析

    http://www.bitscn.com/pdb/php/201411/404680.html 顾名思义,装载器就是加载元素的,使用CI时,经常加载的有: $this->load->li ...

  9. DRF中两大视图基类APIView/GenericAPIView的介绍

    (1)APIView rest_framework.views.APIView APIView是REST framework提供的所有视图的基类,继承自Django的View父类. APIView与V ...

  10. IK分词器原理与源码分析

    原文:http://3dobe.com/archives/44/ 引言 做搜索技术的不可能不接触分词器.个人认为为什么搜索引擎无法被数据库所替代的原因主要有两点,一个是在数据量比较大的时候,搜索引擎的 ...

随机推荐

  1. Oracle中查询表结构的六种方法

    首发微信公众号:SQL数据库运维 原文链接:https://mp.weixin.qq.com/s?__biz=MzI1NTQyNzg3MQ==&mid=2247485212&idx=1 ...

  2. 现代GPGPU 架构汇总

    本篇是GPGPU 架构汇总的总章,参考的是AMD公布OpenCL 手册,该手册总结了AMD. Nvdia 早年的GPGPU体系架构,以及Opencl 各个API 与硬件结构的映射关系.本篇除了整理这两 ...

  3. Docker基础和常用命令

    Docker基础和常用命令 一,Docker 简介 1.1,什么是 Docker Docker 使用 Google 公司推出的 Go 语言 进行开发实现,基于 Linux 内核的 cgroup,nam ...

  4. java学习之spirng的aop

    AOP技术 0x00前言 什么是AOP技术:在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期间动态代理实现程序功能的统一维护的 ...

  5. 2022春每日一题:Day 41

    题目:I Hate It 一个基础的线段树模板,单点修改+区间查询 代码: #include <cstdio> #include <cstdlib> #include < ...

  6. 关于model,modelsmanager,db以及phql之间关系的梳理

    摘要: model在前,db在model后面作为驱动支持.phql是phalcon自创的查询语言,主要特性是在sql语句中用模型名替代表名,其聪明地解析模型类,包括关联关系等,还支持参数绑定.mode ...

  7. nginx转发到uwsgi的配置

    server{ server_name ; listen 80 default_server; add_header Access-Control-Allow-Origin *; add_header ...

  8. 1759D(数位变0)

    题目链接 题目大意: 给你两个整数n, m.你需要求一个数,它满足如下条件: 是n的整数倍,且倍数小于m. 你应该使其末尾的0尽可能的多(如100后面有2个零,1020后面有一个零,我们应该输出100 ...

  9. Cache的相关知识(二)

    1. cache背景知识 为什么的CPU内部需要cache单元?   主要的原因是CPU的速度和内存的速度之间严重不匹配,Cpu处理速度极快,而访问内存慢,cache在这个背景下就诞生了.设计人员通过 ...

  10. 干货 | 如何快速实现 BitSail Connector?

    简介 本文面向 BitSail 的 Connector 开发人员,通过开发者的角度全面的阐述开发一个完整 Connector 的全流程,快速上手 Connector 开发. 目录结构 首先开发者需要通 ...