drf05
内容概要
- 反序列化类校验部分源码解析
- 断言
- drf之请求
- drf之响应
- 视图组件介绍及两个视图基类
- 基于GenericAPIView+5个视图扩展类
反序列化类型校验部分源码解析
入口跟form组件一样is_valide




先看全局钩子

看局部钩子

断言
源码中大量使用try和assert(断言)
关键字assert,断定你是xx,如果不是就抛出异常


drf之请求
-
需求是该接口只能接收
jaon格式数据,不能接收其他格式总共有三个:from rest_framework

api_settings 在drf自己的settings里面

导入三种编码格式
from rest_framework.parsers import JSONParser, FormParser, MultiPartParser方式一:在继承自APIView及其子类的视图类中配置(局部配置)
from rest_framework.views import APIView from rest_framework.response import Response from rest_framework.parsers import JSONParser, FormParser, MultiPartParser class BooksView(APIView): parser_classes = [JSONParser, ] def post(self, request): print(request.data) print(type(request.data)) return Response()



方法二:在django的setting里面写,这个是全局配置





配置文件的应用顺序,先局部----全局---drf默认的。
方式三:全局配 1 个,某个视图类像要三个
在那个视图里面配个局部的 3个即可
drf之响应
-
Response能够响应的编码格式
drf 是django的一个 app,所以需要注册
drf的响应,如果使用浏览器和postman访问同一个接口,返回格式是不用的
drf做个判断,如果是浏览器,返回的格式好看一些如果是postman只要json数据

默认是两种方式,修改方式跟request一样。



同样发get请求,两种返回的格式不一样
因为,在浏览器Response返回的是
BrowsableAPIRenderer


方式二 在django的配置文件里写

方式三:使用顺序(一般就用内置的即可)
优先使用视图类中的配置,其次使用项目配置文件中的配置,最后使用内置的 -
Response的源码属性或方法
class Response(SimpleTemplateResponse): """ An HttpResponse that allows its data to be rendered into arbitrary media types. """ def __init__(self, data=None, status=None, template_name=None, headers=None, exception=False, content_type=None):默认参数
-
data 是返回的数据列表,字典,字符串
ser.data(序列化成字典)---序列化后返回给前端
-
status:http响应的状态码,默认是200,可以自己改
def get(self, request): return Response({"name": 123}, status=300)
drf在
status包下,把所有http响应状态码都写了一遍,常量from rest_framework.status import HTTP_200_OK
def get(self, request): return Response({"name": 123}, status=HTTP_200_OK)
-
template_name:修改响应模板的样子。
-
headers:响应头,http响应的响应头
-原生django怎么在响应头中加东西
def get(self, request): obj = HttpResponse("123") obj['xxx'] = 'yyy' return obj
drf的Response在响应头里加东西def get(self, request): return Response({"name": 123}, status=HTTP_200_OK, headers={"wuhu": 'huhu'})
跨域请求的时候需要在响应头里面添加
-
content_type :响应编码格式,一般不动
-
视图组件介绍及两个视图基类
drf视图,视图类,学过APIView,drf的基类,drf提供的最顶层的类
APIView跟之前的View区别
- 传入到视图方法中的是rest_fromework的Request对象,而不是Django的HttpResponse对象
- 视图方法可以返回rest_fromework的Response对象
- 任何APIException异常都会被不会到,并且处理成合适的响应信息
- 在进行dispatch()分发前,会对请求进行身份认证、权限检测、流量控制
两个视图基类
APIView
-类属性
renderer_classes 响应格式
parser_classes 能够解析的请求格式
authentication_classes 认证类
throttle_classes 频率类
permission_classes 权限类
基于APIView + ModelSerializer + Response写5个接口
视图类
from app01 import models
from .serializer import BookSerializer
class BooksView(APIView):
def get(self, request):
book = models.Book.objects.all()
res = BookSerializer(instance=book, many=True)
return Response(status=HTTP_200_OK, data=res.data)
def post(self, request):
res = BookSerializer(data=request.data)
if res.is_valid():
res.save()
return Response(status=HTTP_200_OK, data={'msg': '添加成功'})
else:
return Response(status=101, data={'msg': res.errors})
class Books2View(APIView):
def get(self, request, pk):
book = models.Book.objects.filter(pk=pk).first()
res = BookSerializer(instance=book)
return Response(res.data)
def put(self, request, pk):
book = models.Book.objects.filter(pk=pk).first()
res = BookSerializer(instance=book, data=request.data)
if res.is_valid():
res.save()
print(11)
return Response(status=HTTP_200_OK, data={'msg': '修改成功'})
else:
return Response(status=101, data={'msg': res.data})
def delete(self, reqeust, pk):
models.Book.objects.filter(pk=pk).delete()
return Response()
序列化类
from rest_framework import serializers
from .models import Book
class BookSerializer(serializers.ModelSerializer):
class Meta:
model = Book
fields = ['name', 'price', 'publish', 'authors', 'publish_dict', 'authors_list']
extra_kwargs = {
'publish': {'write_only': True},
'authors': {'write_only': True}
}
publish_dict = serializers.DictField(read_only=True)
authors_list = serializers.ListField(read_only=True)
模型层
class Book(models.Model):
name = models.CharField(max_length=32, verbose_name="书名")
price = models.CharField(max_length=12, verbose_name="价格")
publish = models.ForeignKey(to='Publish', on_delete=models.CASCADE)
authors = models.ManyToManyField(to='Author')
@property
def publish_dict(self):
return {"name": self.publish.name, "addr": self.publish.addr}
@property
def authors_list(self):
l = [{"name": author_obj.name, "gender": author_obj.gender.get_gender_display()} for author_obj in
self.authors.all()]
return l
class Meta:
verbose_name_plural = '图书表'
def __str__(self):
return "图书对象%s" % self.name
class Publish(models.Model):
name = models.CharField(max_length=32, verbose_name='出版社名称')
addr = models.CharField(max_length=12, verbose_name='出版社地址')
class Meta:
verbose_name_plural = '出版社表'
def __str__(self):
return '出版社对象%s' % self.name
class Author(models.Model):
name = models.CharField(max_length=32, verbose_name='作者名称')
gender = models.OneToOneField(to='AuthorDetail', on_delete=models.CASCADE)
class Meta:
verbose_name_plural = '作者表'
def __str__(self):
return '作者对象%s' % self.name
class AuthorDetail(models.Model):
choice_dict = ((1, '男'), (2, '女'))
gender = models.IntegerField(choices=choice_dict, verbose_name='性别')
class Meta:
verbose_name_plural = '作者详情表'
路由
path('books/', views.BooksView.as_view()),
path('books/<int:pk>/', views.Books2View.as_view())
基于GenericAPIView + 5个视图扩展类
视图类
from rest_framework.mixins import CreateModelMixin # 添加
from rest_framework.mixins import UpdateModelMixin # 修改
from rest_framework.mixins import DestroyModelMixin # 删除
from rest_framework.mixins import RetrieveModelMixin # 查询一个
from rest_framework.mixins import ListModelMixin # 查询所有
from rest_framework.generics import GenericAPIView
class BooksView(GenericAPIView, ListModelMixin, CreateModelMixin):
queryset = models.Book.objects.all() # 查所有
serializer_class = BookSerializer # 序列化类
def get(self, request):
return self.list(request) # 查所有
def post(self, request):
return self.create(request)
class Books2View(GenericAPIView, RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin):
queryset = models.Book.objects.all()
serializer_class = BookSerializer
def get(self, request, *args, **kwargs):
return self.retrieve(request, *args, **kwargs)
def put(self, reqeust, *args, **kwargs):
return self.update(reqeust, *args, **kwargs)
def delete(self, reqeust, *args, **kwargs):
return self.destroy(reqeust, *args, **kwargs)
序列化类
from rest_framework import serializers
from .models import Book
class BookSerializer(serializers.ModelSerializer):
class Meta:
model = Book
fields = ['name', 'price', 'publish', 'authors', 'publish_dict', 'authors_list']
extra_kwargs = {
'publish': {'write_only': True},
'authors': {'write_only': True}
}
publish_dict = serializers.DictField(read_only=True)
authors_list = serializers.ListField(read_only=True)
路由
path('books/', views.BooksView.as_view()),
path('books/<int:pk>/', views.Books2View.as_view())

浙公网安备 33010602011771号