drf快速实现五个接口的方法

全局规定请求格式编码

 # 全局规定请求格式编码,settings文件配置
REST_FRAMEWORK = {
    'DEFAULT_PARSER_CLASSES': [
        'rest_framework.parsers.JSONParser',  # 第一种编码
        'rest_framework.parsers.FormParser',  # 第二种编码
        'rest_framework.parsers.MultiPartParser'  # 第三种编码
    ],
}

# 如果注销第一种编码,也就相当于前端在新增或者修改的时候,提交的数据不能是json格式的编码
# 如果注销第二种编码,也就相当于前端在新增或者修改的时候,提交的数据不能是form-data格式的编码
# 如果注销第三种编码,也就相当于前端在新增或者修改的时候,提交的数据不能是url-encoded格式的编码

# 同样,如果只写一种或者两种,也就是说只接收前端传过来的某一种或者某两种编码格式


# 局部规定请求格式编码,views文件中的视图类中写
parser_classes = [FormParser]  # 括号内代表的是url-encoded编码格式
parser_classes = [JSONParser]  # 括号内代表的是json编码格式数据
parser_classes = [MultiPartParser]  # 代表的是form-data编码格式数据

规定响应格式编码

# 全局规定响应格式编码,settings文件配置

REST_FRAMEWORK = {
    'DEFAULT_RENDERER_CLASSES': [
        'rest_framework.renderers.JSONRenderer',  # 第一种编码格式
        'rest_framework.renderers.BrowsableAPIRenderer',  # 第二种
    ],}

# 如果注销第一种编码,也就相当于后端提交数据(Response返回的时候)不能是json格式的数据返回,而是变成了其他格式的数据
# 如果注销第二种编码,也就相当于后端提交数据(Response返回的时候)不能是浏览器格式的数据返回,而是变成了Json或者其他格式的数据
# 同理如果只写一种,也就是指定那一种编码格式返回到前端
renderer_classes = [JSONParser]
renderer_classes = [BrowsableAPIRenderer]

编码格式规定的优先级是

局部 > 全局(django配置文件) > drf配置文件

Response的参数

data  # 字典或者列表或者字符串,可以将列表或者字典以json格式返回,字符串的话返回到前端还是字符串,返回到前端的数据放在了响应体中
status  # 状态码,可以直接写数字,也可以调drf中的配置常量,相当于填写的数
template_name  # 可以填一个html文件名字,会将该文件返回到前端
headers  # 响应头,可以放一个字典,会以键值对的形式放回给前端响应头里面
content_type  # 响应的编码格式
exception  # 响应的异常信息

视图类的两个视图基类(APIView和GenericAPIView)

# 视图基类APIView和视图基类GenericAPIView的导入方式
from rest_framework.generics import GenericAPIView
from rest_framework.views import APIView

我们发现在写不同表模型类的接口的时候,都大差不差,代码明显冗余,如何解决这种问题,需要用到视图类的两个视图基类
from rest_framework.generics import GenericAPIView
GenericAPIView类有两个重要的类属性
queryset = None
serializer_class = None

可以将这两个类属性写在views类视图函数里面
queryset = models.Book.objects.all()  # 需要序列化的表的所有数据
serializer_class = 序列化器类  # 你要使用的序列化或者反序列化的类

1.虽然有queryset,但是我们一般用get_queryset方法,等同于queryset
 def get(self, request):
        book_queryset = self.queryset  # 对象调用类的属性
        book_queryset = self.get_queryset()  # 对象调用类的方法
        book_queryset = models.Book.objects.all()
前面两个等同于第三个,只不过前面两个继承的是GenericAPIView类
而第三个继承的类是APIView


2.虽然有serializer_class类属性,但是我们一般用get_serializer方法,等同于serializer_class
    def get(self, request):
        book = self.serializer_class(instance=book_queryset, many=True)
        book = self.get_serializer(instance=book_queryset, many=True)
        book = BookSerializers(instance=book_queryset, many=True)
前面两个等同于第三个,只不过前面两个继承的是GenericAPIView类
而第三个继承的类是APIView

3.获取单条模型表的数据
    def get(self,request,pk):
        book_obj = models.Book.objects.filter(pk=pk).first()
        book_obj = self.get_objects()
4.Response返回的时候
正常返回,跟APIView一样
5.总结
首先,路由方面还是不变,分俩个路由
path('books/', views.MyBooks.as_view()),
path('books/<int:pk>/', views.MyBook.as_view())
其次views.py文件中的两个CBV类也不变
class MyBooks   和   class MyBook
---最后这两个视图类MyBooks和MyBook都继承了GenericAPIView类
---继承GenericAPIView类
---两个类属性:
    queryset = None
    serializer_class = None
---三个方法:
    self.get_object()  # 获取models表中的单条数据
    self.get_serializer(instance=None,data=None)
    self.get_queryset()  # 获取要序列化的数据

五个视图扩展类()

基于两个视图基类的进一步封装,让代码冗余减少
继承GenericAPIView类加五个视图扩展类
五个试图扩展类
from rest_framework.mixins import ListModelMixin          get
from rest_framework.mixins import RetrieveModelMixin      get
from rest_framework.mixins import UpdateModelMixin        put
from rest_framework.mixins import DestroyModelMixin       delete
from rest_framework.mixins import CreateModelMixin        post

首先我们需要在views的视图类继承GenericAPIView+任意一个五个视图扩展类
1.如果加的是ListModelMixin视图扩展类,那么就相当于get获取所有图书信息
class MyBooks(GenericAPIView,ListModelMixin):
    queryset = models.Book.objects.all()
    serializer_class = BookSerializers
    def get(self,request):
        return self.list(request)
2.如果想新增一个数据,需要加CreateModelMixin视图扩展类
    def post(self,request):
        return self.create(request)
    需要注意的是它还有一个perform_create(self,serializer)方法,该方法是保存校验通过的数据,我们可以通过对他的重写,从而达到当保存多表的时候,实现实时的更新.serializer是校验通过的数据serializer.save()
3.如果想获取一个图书信息,需要用到RetrieveModelMixin试图扩展类
    def get(self, request, *args, **kwargs):
        return self.retrieve(request, *args, **kwargs)
4.如果想修改一个图书信息,需要用到UpdateModelMixin视图扩展类
    def put(self,request,*args,**kwargs):
        return self.update(request,*args,**kwargs)
    
5.如果想删除一个图书信息,需要用到DestroyModelMixin视图扩展类
    def delete(self,request,*args,**kwargs):
        return self.destroy(request,*args,**kwargs)
需要注意的是它也写了一个方法perform_destroy(self,instance)
我们可以重写这个方法,在删除之前做一点事情


6.总结,GenericAPIView类加五个视图扩展类写五个接口的步骤
首先,路由方面还是不变,分俩个路由
path('books/', views.MyBooks.as_view()),
path('books/<int:pk>/', views.MyBook.as_view())
其次views.py文件中的两个CBV类也不变
class MyBooks   和   class MyBook

# 最后是MyBooks类继承了GenericAPIView加两个视图扩展类
# MyBook类继承了GenericAPIView加三个视图扩展类

九个视图子类()

# 九个视图子类的模块导入如下
from rest_framework.generics import ListAPIView
from rest_framework.generics import CreateAPIView
from rest_framework.generics import ListCreateAPIView
from rest_framework.generics import RetrieveAPIView
from rest_framework.generics import UpdateAPIView
from rest_framework.generics import DestroyAPIView
from rest_framework.generics import RetrieveUpdateAPIView
from rest_framework.generics import RetrieveDestroyAPIView
from rest_framework.generics import RetrieveUpdateDestroyAPIView

1.视图子类ListAPIView  # 等同于写了一个获取所有图书的get请求方式的接口
视图子类ListAPIView = 视图基类GenericAPIView + 视图扩展类ListModelMixin
class ListAPIView(mixins.ListModelMixin,
                  GenericAPIView):
ListAPIView视图子类继承了ListModelMixin视图扩展类和GenericAPIView视图基类
2.视图子类CreateAPIView  # 等同于写了一个新增一个图书的post请求方式的接口
视图子类CreateAPIView = 视图基类GenericAPIView + 视图扩展类CreateModelMixin
class CreateAPIView(mixins.CreateModelMixin,
                    GenericAPIView):

3.视图子类RetrieveAPIView  # 等同于写了一个查询一本图书的get请求方式的接口
视图子类RetrieveAPIView = 视图基类GenericAPIView + 视图扩展类RetrieveModelMixin
class RetrieveAPIView(mixins.RetrieveModelMixin,
                      GenericAPIView):
4.视图子类UpdateAPIView  # 等同于写了一个修改一本图书的put请求方式的接口
视图子类UpdateAPIView = 视图基类GenericAPIView + 视图扩展类UpdateModelMixin
class UpdateAPIView(mixins.UpdateModelMixin,
                    GenericAPIView):
5.视图子类DestroyAPIView  # 等同于写了一个删除一本图书的delete请求方式的接口
视图子类DestroyAPIView = 视图基类GenericAPIView + 视图扩展类DestroyModelMixin
class DestroyAPIView(mixins.DestroyModelMixin,
                     GenericAPIView):
    
6.视图子类ListCreateAPIView  # 等同于写了一个获取所有图书和新增一本图书的get和post请求方式的两个接口
视图子类ListCreateAPIView = 视图基类GenericAPIView + 视图扩展类ListModelMixin + 视图扩展类CreateModelMixin
class ListCreateAPIView(mixins.ListModelMixin,
                        mixins.CreateModelMixin,
                        GenericAPIView):
7.视图子类RetrieveUpdateAPIView  # 等同于写了一个获取一本图书和修改一本图书的get和put请求方式的两个接口
视图子类RetrieveUpdateAPIView = 视图基类GenericAPIView + 视图扩展类RetrieveModelMixin + 视图扩展类UpdateModelMixin
class RetrieveUpdateAPIView(mixins.RetrieveModelMixin,
                            mixins.UpdateModelMixin,
                            GenericAPIView):
8.视图子类RetrieveDestroyAPIView  # 等同于写了一个获取一本图书和删除一本图书的get和delete请求方式的两个接口
视图子类RetrieveDestroyAPIView = 视图基类GenericAPIView + 视图扩展类
RetrieveModelMixin + 视图扩展类DestroyModelMixin
class RetrieveDestroyAPIView(mixins.RetrieveModelMixin,
                             mixins.DestroyModelMixin,
                             GenericAPIView):
9.视图子类RetrieveUpdateDestroyAPIView  # 等同于写了一个获取一本图书和修改一本图书以及删除一本图书的get和put和delete请求方式的三个接口
视图子类RetrieveUpdateDestroyAPIView = 视图基类GenericAPIView + 视图扩展类RetrieveModelMixin + 视图扩展类UpdateModelMixin + 视图扩展类DestroyModelMixin
class RetrieveUpdateDestroyAPIView(mixins.RetrieveModelMixin,
                                   mixins.UpdateModelMixin,
                                   mixins.DestroyModelMixin,
                                   GenericAPIView):
10.总结
首先,路由方面还是不变,分俩个路由
path('books/', views.MyBooks.as_view()),
path('books/<int:pk>/', views.MyBook.as_view())
其次views.py文件中的两个CBV类也不变
class MyBooks   和   class MyBook
--只需要继承你想要实现的接口类
--随机组合,只要满足五个接口就可以

视图集

# 四个视图集,需要导入视图集模块
from rest_framework.viewsets import ModelViewSet
from rest_framework.viewsets import ReadOnlyModelViewSet
from rest_framework.viewsets import ViewSet
from rest_framework.viewsets import GenericViewSet 
1.视图集ModelViewSet  # 等同于写了获取所有,获取单个,新增一个,修改一个,删除一个的get,get,post,put,delete五个请求方式的接口
视图集ModelViewSet = 视图基类的子类GenericViewSet + ListModelMixin视图扩展类
+ 视图扩展类CreateModelMixin + 视图扩展类RetrieveModelMixin 
+ 视图扩展类UpdateModelMixin + 视图扩展类DestroyModelMixin
class ModelViewSet(mixins.CreateModelMixin,
                   mixins.RetrieveModelMixin,
                   mixins.UpdateModelMixin,
                   mixins.DestroyModelMixin,
                   mixins.ListModelMixin,
                   GenericViewSet):
2.视图集ReadOnlyModelViewSet
class ReadOnlyModelViewSet(mixins.RetrieveModelMixin,
                           mixins.ListModelMixin,
                           GenericViewSet):
    pass
3.视图集ViewSet  # 等同于APIView + ViewSetMixin
class ViewSet(ViewSetMixin, views.APIView):
    pass
4.GenericViewSet  # 等同于GenericAPIView + ViewSetMixin
class GenericViewSet(ViewSetMixin, generics.GenericAPIView):
    pass
5.视图集的父类GenericViewSet
class GenericViewSet(ViewSetMixin, generics.GenericAPIView):
6.视图集ModelViewSet的父类GenericViewSet的父类ViewSetMixin
所以说我们在as_view方法里面填字典能够映射,是该类实现的
路由匹配成功执行-->as_view方法,该方法是ViewSetMixin的as_view--->执行之后,他会将字典for循环解压赋值成key,value的形式,其中通过getattr反射自己创建的类获取value函数的内存地址,然后再通过setattr将key的内存地址替换成了value函数的内存地址--->执行value()-->后面的就跟View执行的流程大差不大了
# 所以说只要继承了ViewSetMixin类,路由写法就发生了变化,视图类中方法可以随意命名,只需要再路由中映射即可,也就是value值改变就可以

7.总结
首先,路由方面跟前面的大差不差,分俩个路由,唯一的区别是as_view里面有参数,该参数是字典的形式,字典中的key代表请求方式,字典中的value代表的是该请求方式发出时候需要执行的函数。如{'get':'name','post':'egon'}
比如get请求方式发出的时候,会执行name函数,post请求发出的时候会执行egon函数。当然前提肯定是路由匹配成功,


# views.py文件中的代码
from rest_framework.viewsets import ModelViewSet
class MyBooks(ModelViewSet):
    queryset = models.Book.objects.all()
    serializer_class = 序列化器类内存地址
    
# 路由urls.py中的代码
path('books/', views.MyBooks.as_view({'get':'list','post':'create'})),
path('books/<int:pk>/', views.MyBook.as_view({'get':'retrieve','put':'update','delete':'destroy'}))
需要知道每个关键的方法都在那个父类def list():  # 在ListModelMixin中写了list方法    passdef create():  # 在CreateModelMixin中写了create方法    passdef retrieve():  # 在RetrieveModelMixin中写了retrieve方法    passdef update():  # 在UpdateModelMixin中写了update方法    passdef destroy():  # 在DestroyModelMixin中写了destroy方法    passdef perform_create(self,serializer):    pass    # 在CreateModelMixin中写了perform_create方法    # 这个是post请求方式来的时候执行post函数中的create函数中的perform_create函数,该函数是专门创建新数据的函数def perform_destroy(self,instance):    pass    # 在DestroyModelMixin中写了perform_destroy方法    # 这个是delete请求方式来的时候执行delete函数中的perform_destroy函数,该函数是专门处理删除数据的函数
视图集ModelViewSet-->GenericViewSet-->视图基类GenericAPIView-->视图基类APIView-->View-->object视图集ModelViewSet-->GenericViewSet-->ViewSetMixin-->object视图集ModelViewSet有6个父类
posted @ 2021-11-04 19:06  Aisa  阅读(334)  评论(0)    收藏  举报