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. 基于LZO的高性能无损数据压缩IP

    LZOAccel-C LZO Data Compression Core/无损数据压缩IP Core LZOAccel-C是一个无损数据压缩引擎的FPGA硬件实现,兼容LZO 2.10标准. Core ...

  2. 再来一次,新技术搞定老业务「GitHub 热点速览 v.22.44」

    上上周 Next.js 新版本火了一把,这不本周热点趋势就有了一个 Next.js 13 新特性构建的网站,虽然它只是个实验性项目.同样可以搞定一些业务的还有 lama-cleaner,不过它并不是个 ...

  3. webpack4--按需加载

    在做单页面应用的过程中,通常利用webpack打包文件,将依赖的外部问价单独打一个vendor.js.这样就会有个问题,这个文件会随着你引用的包的增多,体积会越来越大.在路由中利用import 引用文 ...

  4. Java计算文件或文件夹大小

    导入此类后,直接调用FilesUtil.returnSizi(String path),即可获取文件或者文件夹大小. 代码: 1 /** 2 * 路人甲操作文件的工具类 3 * returnSizi( ...

  5. ubuntu生成pem证书连接服务器(已验证)

    SSH 密钥认证是什么? 与用户密码登录相比,SSH 密钥认证更安全,因为只有拥有密钥的人才能连接,并且密钥通过不同的算法进行了很好的加密.它还通过无密码登录使 SSH 连接变得简单. 这个搞两个方案 ...

  6. 表单的子元素可不在form标签内

    表单是网页用于向服务器发送数据的元素.其用法类似下面: <form method="POST" action="/login"> <input ...

  7. 13、设计一个函数process,在你调用他的时候,每次实现不同的功能,输入a,b两个数, 第一次调用时找出a,b中的最大者。 第二次找出最小者,,第三次求两个数的和。

    /* 设计一个函数process,在你调用他的时候,每次实现不同的功能,输入a,b两个数, 第一次调用时找出a,b中的最大者. 第二次找出最小者,,第三次求两个数的和. */ #include < ...

  8. ubuntu 18.04安装tensorflow (CPU)

    在已经安装anaconda环境及pip之后. 添加并设置pip配置文件: mkdir ~/.pip vim ~/.pip/pip.conf pip.conf文件内容: [global] index-u ...

  9. 【Spring系列】- Spring循环依赖

    Spring循环依赖 生命不息,写作不止 继续踏上学习之路,学之分享笔记 总有一天我也能像各位大佬一样 一个有梦有戏的人 @怒放吧德德 分享学习心得,欢迎指正,大家一起学习成长! 目录 Spring循 ...

  10. 利用云服务提供商的免费证书,在服务器上发布https前端应用和WebAPI的应用

    我们如果要在服务器上发布https前端应用和WebAPI的应用,那么我们就需要用到https证书了.我们一般发布的应用的云服务器上,都会提供一定量的相关的免费证书(一般为20个)供我们使用,每个一年期 ...