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个父类

浙公网安备 33010602011771号