drf请求和响应、2基类、5个视图扩展类、9个视图子类
1、
视图类继承APIView后多了 -0 去除了csrf认证 -1 新的request -request.data -request.query_params -request.其他跟之前一样 -request._request 是老的 -2 三大认证 -3 全局异常
JSONParser: 解析json格式
FormParser: 默认的编码 urlencoded
MultiPartParser: 传文件格式 form-data
from rest_framework.views import APIView from rest_framework.response import Response from rest_framework.parsers import JSONParser, FormParser, MultiPartParser from rest_framework.renderers import JSONRenderer, BrowsableAPIRenderer
局部限制
写一个类属性 parser_classes = [JSONParser或者FormParser、MultiPartParser]
class BookView(APIView): # 类属性 parser_classes = [JSONParser] def get(self, request): res = Response(data={123}, status=500, headers={'xxx': 'yyy'}) print(res.data) return res def post(self, request): print(self.parser_classes) print(request.data) return Response('新增')
效果:
全局限制
REST_FRAMEWORK = { #####请求体的限制 'DEFAULT_PARSER_CLASSES': [ 'rest_framework.parsers.JSONParser', 'rest_framework.parsers.FormParser', # 'rest_framework.parsers.MultiPartParser' ], #####响应格式的限制 'DEFAULT_RENDERER_CLASSES': [ 'rest_framework.renderers.JSONRenderer', 'rest_framework.renderers.BrowsableAPIRenderer', ], }
补充:
全局使用后,局部再限制---》只需要在视图类上加即可
全局如果用了,局部这样配,优先用局部的,也就是这个类管理的接口,只能接收form-data格式 parser_classes = [MultiPartParser]
二、
1、
# from rest_framework.response import Response ### __init__ 中需要传这几个参数,不传也可以 data=None # 字典,列表,字符串,空赋值给它---》http响应体中 ---》第一个参数是它 status=None, # http响应状态码,默认是200,千万不能写成1xx headers=None, # http响应头,后期我们可以往响应头中放数据 content_type=None # 响应编码格式(不用管,用浏览器访问就是:text/html,用postman就是:json格式) template_name=None # 模版名字 默认是:rest_framework/api.html 了解,可以定制自己返回的页面样子 ###补充:后面会用---》通过res.data 就能取到当时放的datga res=Response(data={},status=500,headers={'xxx':'yyy'}) print(res.data) return res ### 补充:取当时放的响应头 res.headers 拿不到数据,可以通过下面的方式或得到 print(res['xxx']) print(res.has_header('zzz'))
serializer 类中序列化后的字段,通过 Response(ser.data)第一个参数赋值给data
publish_detail = serializers.DictField(read_only=True) author_list = serializers.ListField(read_only=True)
2、
响应有编码格式:默认支持json和text/html(浏览器)
# 修改只支持json ### 局部使用 class BookView(APIView): renderer_classes = [BrowsableAPIRenderer] ### 全局使用 REST_FRAMEWORK = { 'DEFAULT_RENDERER_CLASSES': [ 'rest_framework.renderers.JSONRenderer', 'rest_framework.renderers.BrowsableAPIRenderer', ], } ##局部禁用---》全局已经配置了---》局部想用浏览器的样子 class BookView(APIView): renderer_classes = [BrowsableAPIRenderer] # 如果不配置---》有默认 -解析:三种编码都能解析 -响应:浏览器访问看到浏览器的样子,postman访问,看到json格式
3、基于原生的django,向响应头写入数据
from django.http import HttpResponse def custom_header_view(request): # 创建一个HttpResponse对象 response = HttpResponse("Hello, World!") # 向响应头添加自定义信息 response['X-Custom-Header'] = 'this is a test' return response
三、两个基类APIView和GenericAPIView
基于 GenericAPIView 写接口
1、GenericAPIView 源码内容
# GenericAPIView 有类属性和方法 ### 重要属性### -queryset:以后放所有某个表查询出的数据 -serializer_class:要序列化的类 ### 重要方法### -get_queryset :要序列化的所有数据,qs对象 -get_serializer :序列化类 -get_object :修改,查询的单条 ## 了解类属性: -lookup_field = 'pk' 路由使用转换器,转换出来的参数,查询单条要用到,如果改了,路由对应也要修改,一般不改 -filter_backends:后面详细讲 过滤 功能 -pagination_class :后面详细讲 分页 ### 了解方法 -get_serializer_class 后期咱们可能会重写它,指定某些方法使用不同的序列化类 -filter_queryset 后面跟过滤功能一起讲
补充:手写GenericAPIView
两个类属性,三个方法
class GenericAPIView(APIView): queryset = None serializer_class = None def get_queryset(self): return self.queryset.all() # 真正使用的时候,再加all获取所有才行 def get_serializer(self, *args, **kwargs): return self.serializer_class(*args, **kwargs) def get_object(self, pk): res = self.get_queryset() return res.filter(pk=pk).first()
2、案例代码
view
class PublishView(GenericAPIView): # 定义两个类属性,方便用的时候进行替换 queryset = Publish.objects.all() serializer_class = PublishSerializer def get(self, request): obj_list = self.get_queryset() ser = self.get_serializer(instance=obj_list, many=True) return Response(ser.data) def post(self, request): ser = self.get_serializer(data=request.data) if ser.is_valid(): ser.save() return Response({'code': 200, "data": ser.data, 'msg': "添加成功"}) else: return Response(ser.errors) class PublishDetailView(GenericAPIView): queryset = Publish.objects.all() # 表数据查询结果 serializer_class = PublishSerializer # 序列化实例 def get(self, request, pk): obj = self.get_object() ser = self.get_serializer(instance=obj) return Response(ser.data) def put(self, request, pk): obj = self.get_object() ser = self.get_serializer(instance=obj, data=request.data) if ser.is_valid(): ser.save() return Response({'code': 200, "data": ser.data, 'msg': "修改成功"}) return Response(ser.errors) def delete(self, request, pk): self.get_object().delete() return Response('删除成功!')
注意:
-get_object方法 :修改,查询单条、删除使用
serializer
class PublishSerializer(serializers.ModelSerializer): class Meta: model = Publish # fields = '__all__' fields = ['name', 'addr']
四、五
ListModelMixin :查询所有记录
CreateModelMixin:新增记录
UpdateModelMixin:修改某一条记录
DestroyModelMixin:删除某一条记录
RetrieveModelMixin:查询一条记录
1、view
from rest_framework.mixins import ListModelMixin, CreateModelMixin, UpdateModelMixin, DestroyModelMixin, \ RetrieveModelMixin class PublishView(GenericAPIView, ListModelMixin, CreateModelMixin): queryset = Publish.objects.all() serializer_class = PublishSerializer def get(self, request): return self.list(request) def post(self, request): return self.create(request) class PublishDetailView(GenericAPIView, RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin): queryset = Publish.objects.all() serializer_class = PublishSerializer def put(self, request, pk): return self.update(request, pk) def get(self, request, pk): return self.retrieve(request, pk) def delete(self, request, pk): return self.destroy(request, pk)
补充:ListModelMixin 扩展类的源码,里面用到了GenericeAPIView的get_queryset()、get_serializer() 两个方法。
在视图类中 return self.list(request) 就是利用ListModelMixin 扩展类做了序列化和反序列化操作、resturn Response(serizlizer.data)
def list(self, request, *args, **kwargs): queryset = self.filter_queryset(self.get_queryset()) page = self.paginate_queryset(queryset) if page is not None: serializer = self.get_serializer(page, many=True) return self.get_paginated_response(serializer.data) serializer = self.get_serializer(queryset, many=True) return Response(serializer.data)
2、serializer
class PublishSerializer(serializers.ModelSerializer): class Meta: model = Publish # fields = '__all__' fields = ['name', 'addr']
五、九个视图子类
1、九个视图子类分类
不带pk的
ListAPIView, CreateAPIView, ListCreateAPIView
带pk的
RetrieveAPIView, UpdateAPIView, DestroyAPIView
RetrieveUpdateDestroyAPIView, RetrieveDestroyAPIView, RetrieveUpdateAPIView
2、有了这九个视图子类可以大大减少代码量
导入:九个视图子类有继承 GenericAPIView,它们都可以从.generics 里导入
from rest_framework.generics import ListCreateAPIView
class PublishView(ListAPIView, ListCreateAPIView, CreateAPIView): queryset = Publish.objects.all() serializer_class = PublishSerializer class PublishDetailView(RetrieveUpdateDestroyAPIView): queryset = Publish.objects.all() serializer_class = PublishSerializer
注:
以后想写5个接口中的某一个或某几个或所有,只需要选择继承不同的类即可,类中只需要配置两个类属性
没有继承的类相应的接口就没法使用
3、路由和序列化文件不变和之前写法一致
###路由 from django.urls import path from app01.views import PublishView, PublishDetailView urlpatterns = [ path('publishs/', PublishView.as_view()), path('publishs/<int:pk>', PublishDetailView.as_view()), ] ###序列化文件 class PublishSerializer(serializers.ModelSerializer): class Meta: model = Publish # fields = '__all__' fields = ['name', 'addr']