欢迎您访问365答案网,请分享给你的朋友!
生活常识 学习资料

drf快速入门03--

时间:2023-05-18
1、继承关系

图片来源https://blog.csdn.net/LHQ626/article/details/118400296

2. GenericAPIView[通用视图类] 2.1、GenericAPIView介绍

a、继承自APIVIew,

b、主要增加了操作序列化器和数据库查询的方法,作用是为下面Mixin扩展类的执行提供方法支持。

c、通常在使用时,可搭配一个或多个Mixin扩展类。

2.2、属性及方法介绍

属性

queryset 

指明表模型对象

serializer_class

指明视图使用的序列化器

 lookup_field = 'pk'

路由有名分组用的,这也就是有名分组,为什么只能填pk,因为这里写死了,如果我们想要有名分组的变量,叫xxx需要在外部视图配置一下lookup_field = 'xxx'

filter_backends

# 默认内部查询的静态字段filter_backends = api_settings.DEFAULT_FILTER_BACKENDS

pagination_class  

默认内部分页用的静态字段pagination_class = api_settings.DEFAULT_PAGINATION_CLASS

方法

get_serializer_class(self)

外部使用当出现一个视图类中调用多个序列化器时,那么可以通过条件判断在get_serializer_class方法中,通过返回不同的序列化器类名就可以让视图方法执行不同的序列化器对象了。# 当试图中使用多个序列化器类时,可以使用该方法来区分class OrderView(CreateAPIView): queryset = models.Order.objects.filter(is_deleted=False, is_show=True) serializer_class = get_serializer_class def get_serializer_class(self): if self.request.method == 'GET': return StudentModelSerializer1 return StudentModelSerializer2

 get_queryset(self)

一般内部使用,但是外部可以重写获得reuqest返回视图使用的查询集,主要用来提供给Mixin扩展类使用,是列表视图与详情视图获取数据的基础,默认返回`queryset`属性。重写帮助视图拿到request,比如可以用于ListAPIViewclass OrderDataView(ListAPIView): """查询属于与自己的订单""" permission_classes = [IsAuthenticated, ] serializer_class = OrderDataModelSerializer def get_queryset(self): queryset = models.Order.objects.filter(user=self.request.user, is_deleted=False) return queryset

 get_object(self)

外部使用返回详情视图所需的模型类数据对象,主要用来提供给Mixin扩展类使用。在试图中可以调用该方法获取详情信息的模型类对象。若详情访问的模型类对象不存在,会返回404.# get_object()方法根据pk参数查找queryset中的数据对象该方法会默认使用APIView提供的check_object_permissions方法检查当前对象是否有权限被访问。class BookDetailView(GenericAPIView): queryset = BookInfo.objects.all() serializer_class = BookInfoSerializer def get(self, request, pk): book = self.get_object() # get_object()方法根据pk参数查找queryset中的数据对象 serializer = self.get_serializer(book) return Response(serializer.data)

 get_serializer(self, *args, **kwargs)/get_serializer_context(self)

两个都是内部使用get_serializer(self, *args, **kwargs)其返回一个serializer_class内部使用的,一般外部不用。外部使用:self.get_serializer()()调用封装request的方法,把request给封装进了context,以后self.context.get('request'),就可以拿到requestdef get_serializer(self, *args, **kwargs): serializer_class = self.get_serializer_class() kwargs.setdefault('context', self.get_serializer_context()) return serializer_class(*args, **kwargs)# get_serializer_context(self) # 封装request的方法def get_serializer_context(self): return { 'request': self.request, 'format': self.format_kwarg, 'view': self }

get_serializer_class

内部使用外部配置的serializer_class,被其进行相关的处理def get_serializer_class(self): assert self.serializer_class is not None, ( "'%s' should either include a `serializer_class` attribute, " "or override the `get_serializer_class()` method." % self.__class__.__name__ ) return self.serializer_class

filter_queryset(self, queryset)

# 内部使用# 过滤用的,def filter_queryset(self, queryset): for backend in list(self.filter_backends): queryset = backend().filter_queryset(self.request, queryset, self) return queryset

paginate_queryset(self, queryset)

# 内部使用# 分页处理def paginate_queryset(self, queryset): if self.paginator is None: return None return self.paginator.paginate_queryset(queryset, self.request, view=self)

2.3. 基于GenericAPIView写的接口 

# views.pyclass Book2View(GenericAPIView): #queryset要传queryset对象,查询了所有的图书 # serializer_class使用哪个序列化类来序列化这堆数据 queryset=Book.objects # queryset=Book.objects.all() serializer_class = BookSerializer def get(self,request): book_list=self.get_queryset() book_ser=self.get_serializer(book_list,many=True) return Response(book_ser.data) def post(self,request): book_ser = self.get_serializer(data=request.data) if book_ser.is_valid(): book_ser.save() return Response(book_ser.data) else: return Response({'status':101,'msg':'校验失败'})class Book2DetailView(GenericAPIView): queryset = Book.objects serializer_class = BookSerializer def get(self, request,pk): book = self.get_object() book_ser = self.get_serializer(book) return Response(book_ser.data) def put(self, request,pk): book = self.get_object() book_ser = self.get_serializer(instance=book,data=request.data) if book_ser.is_valid(): book_ser.save() return Response(book_ser.data) else: return Response({'status': 101, 'msg': '校验失败'}) def delete(self,request,pk): ret=self.get_object().delete() return Response({'status': 100, 'msg': '删除成功'}) #url.py # 使用GenericAPIView重写的 path('books2/', views.Book2View.as_view()), re_path('books2/(?Pd+)', views.Book2DetailView.as_view()),

3、5个视图扩展类mixins 3.1 mixins介绍

a、提供了几种后端视图(对数据资源进行曾删改查)处理流程的实现,

b、如果需要编写的视图属于这五种,则视图可以通过继承相应的扩展类来复用代码,减少自己编写的代码量。

c、这五个扩展类需要搭配GenericAPIView父类,因为五个扩展类的实现需要调用GenericAPIView提供的序列化器与数据库查询的方法。

3.2 mixins源码

CreateModelMixin,RetrieveModelMixin,UpdateModelMixin,DestroyModelMixin,ListModelMixin,class ListModelMixin: """ List a queryset. """ 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)class RetrieveModelMixin: """ Retrieve a model instance. """ def retrieve(self, request, *args, **kwargs): instance = self.get_object() serializer = self.get_serializer(instance) return Response(serializer.data)class UpdateModelMixin: """ Update a model instance. """ def update(self, request, *args, **kwargs): partial = kwargs.pop('partial', False) instance = self.get_object() serializer = self.get_serializer(instance, data=request.data, partial=partial) serializer.is_valid(raise_exception=True) self.perform_update(serializer) if getattr(instance, '_prefetched_objects_cache', None): # If 'prefetch_related' has been applied to a queryset, we need to # forcibly invalidate the prefetch cache on the instance. instance._prefetched_objects_cache = {} return Response(serializer.data) def perform_update(self, serializer): serializer.save() def partial_update(self, request, *args, **kwargs): kwargs['partial'] = True return self.update(request, *args, **kwargs)class DestroyModelMixin: """ Destroy a model instance. """ def destroy(self, request, *args, **kwargs): instance = self.get_object() self.perform_destroy(instance) return Response(status=status.HTTP_204_NO_CONTENT) def perform_destroy(self, instance): instance.delete()

3.3 基于GenericAPIView和5个视图扩展类写的接口

from rest_framework.mixins import ListModelMixin,CreateModelMixin,UpdateModelMixin,DestroyModelMixin,RetrieveModelMixin# views.pyclass Book3View(GenericAPIView,ListModelMixin,CreateModelMixin): queryset=Book.objects serializer_class = BookSerializer def get(self,request): return self.list(request) def post(self,request): return self.create(request)class Book3DetailView(GenericAPIView,RetrieveModelMixin,DestroyModelMixin,UpdateModelMixin): queryset = Book.objects serializer_class = BookSerializer def get(self, request,pk): return self.retrieve(request,pk) def put(self, request,pk): return self.update(request,pk) def delete(self,request,pk): return self.destroy(request,pk)# urls.py # 使用GenericAPIView+5 个视图扩展类 重写的 path('books3/', views.Book3View.as_view()), re_path('books3/(?Pd+)', views.Book3DetailView.as_view()),

4 GenericAPIView的视图子类 4.1 GenericAPIView的子类介绍

a、视图子类,也叫通用视图子类。

b、继承了GenericAPIView,以及Mixin,真正的实现了几行代码,完成一个视图

c、其实就是帮你,return了视图中手动return的方法

1)CreateAPIView提供 post 方法继承自: GenericAPIView、CreateModelMixin2)ListAPIView提供 get 方法继承自:GenericAPIView、ListModelMixin3)RetrieveAPIView提供 get 方法继承自: GenericAPIView、RetrieveModelMixin4)DestoryAPIView提供 delete 方法继承自:GenericAPIView、DestoryModelMixin5)UpdateAPIView提供 put 和 patch 方法继承自:GenericAPIView、UpdateModelMixin6)RetrieveUpdateAPIView提供 get、put、patch方法继承自: GenericAPIView、RetrieveModelMixin、UpdateModelMixin7)RetrieveUpdateDestoryAPIView提供 get、put、patch、delete方法继承自:GenericAPIView、RetrieveModelMixin、UpdateModelMixin、DestoryModelMixin

4.2 GenericAPIView的视图子类&Mixin书写接口

"""使用GenericAPIView的视图子类进一步简化开发api接口的代码"""from rest_framework.generics import ListAPIView,CreateAPIViewclass Students3GenericAPIView(ListAPIView,CreateAPIView): queryset = Student.objects.all() serializer_class = StudentModelSerializerfrom rest_framework.generics import RetrieveAPIView,UpdateAPIView,DestroyAPIViewfrom rest_framework.generics import RetrieveUpdateDestroyAPIView # 结合了上面三个子类的功能class Student3GenericAPIView(RetrieveUpdateDestroyAPIView): queryset = Student.objects.all() serializer_class = StudentModelSerializer

5. 视图集基类viewsets 5.1 源码分析ViewSetMixin

# 重写了as_view# 核心代码(所以路由中只要配置了对应关系,比如{'get':'list'}),当get请求来,就会执行list方法for method, action in actions.items(): #method:get # action:list handler = getattr(self, action) #执行完上一句,handler就变成了list的内存地址 setattr(self, method, handler) #执行完上一句 对象.get=list #for循环执行完毕 对象.get:对着list 对象.post:对着create

5.2 继承ViewSetMixin的视图类

# views.pyfrom rest_framework.viewsets import ViewSetMixinclass Book6View(ViewSetMixin,APIView): #一定要放在APIVIew前 def get_all_book(self,request): print("xxxx") book_list = Boaok.objects.all() book_ser = BookSerializer(book_list, many=True) return Response(book_ser.data) # urls.py #继承ViewSetMixin的视图类,路由可以改写成这样 path('books6/', views.Book6View.as_view(actions={'get': 'get_all_book'})),

5.3 viewsets数量

class ViewSet(ViewSetMixin, views.APIView): """ The base ViewSet class does not provide any actions by default. """ passclass GenericViewSet(ViewSetMixin, generics.GenericAPIView): """ The GenericViewSet class does not provide any actions by default, but does include the base set of generic view behavior, such as the `get_object` and `get_queryset` methods. """ passclass ReadonlyModelViewSet(mixins.RetrieveModelMixin, mixins.ListModelMixin, GenericViewSet): """ A viewset that provides default `list()` and `retrieve()` actions. """ passclass ModelViewSet(mixins.CreateModelMixin, mixins.RetrieveModelMixin, mixins.UpdateModelMixin, mixins.DestroyModelMixin, mixins.ListModelMixin, GenericViewSet): """ A viewset that provides default `create()`, `retrieve()`, `update()`, `partial_update()`, `destroy()` and `list()` actions. """ pass

5.4 使用ModelViewSet快速编写5个接口

(看着玩就行,一般不用他,封装程度太高)

# 1、views.py ViewSetMixin,APIViewfrom rest_framework.viewsets import ViewSetMixinclass Book6View(ViewSetMixin,APIView): #一定要放在APIVIew前 def get_all_book(self,request): print("xxxx") book_list = Boaok.objects.all() book_ser = BookSerializer(book_list, many=True) return Response(book_ser.data) # urls.py #继承ViewSetMixin的视图类,路由可以改写成这样 path('books6/', views.Book6View.as_view(actions={'get': 'get_all_book'})),"""2、ViewSet 使用视图集把上面的两个视图类组成一个视图类"""from rest_framework.viewsets import ViewSetclass StudentViewSet(ViewSet): def get_all(self,request): """获取所有学生信息""" data_list = Student.objects.all() serializer = StudentModelSerializer(instance=data_list, many=True) return Response(serializer.data) def add_student(self,request): return Response({"message":"添加成功!"}) def get_one(self,request,pk): """获取一个学生信息""" instance = Student.objects.get(pk=pk) serializer = StudentModelSerializer(instance=instance) return Response(serializer.data)# 3、ViewSet,ListAPIView,CreateAPIView,RetrieveAPIView"""发挥下ViewSet的作用"""from rest_framework.viewsets import ViewSetfrom rest_framework.generics import ListAPIView,CreateAPIView,RetrieveAPIViewclass Student2ViewSet(ViewSet,ListAPIView,CreateAPIView,RetrieveAPIView): queryset = Student.objects.all() serializer_class = StudentModelSerializer def get_all(self,request): """获取所有学生信息""" return self.list(request) def add_student(self,request): return self.create(request) def get_one(self,request,pk): """获取一个学生信息""" return self.retrieve(request)# 4 GenericViewSet,ListModelMixin,CreateModelMixin,RetrieveModelMixinfrom rest_framework.viewsets import GenericViewSetfrom rest_framework.mixins import ListModelMixin,CreateModelMixin,RetrieveModelMixinclass Student3ViewSet(GenericViewSet,ListModelMixin,CreateModelMixin,RetrieveModelMixin): queryset = Student.objects.all() serializer_class = StudentModelSerializer def get_all(self,request): """获取所有学生信息""" return self.list(request) def add_student(self,request): return self.create(request) def get_one(self,request,pk): """获取一个学生信息""" return self.retrieve(request)# 5 GenericViewSet,ListModelMixin,CreateModelMixin,RetrieveModelMixin,UpdateModelMixin,DestroyModelMixin"""简化上面的代码"""from rest_framework.viewsets import GenericViewSetfrom rest_framework.mixins import ListModelMixin,CreateModelMixin,RetrieveModelMixin,UpdateModelMixin,DestroyModelMixinclass Student4ViewSet(GenericViewSet,ListModelMixin,CreateModelMixin,RetrieveModelMixin,UpdateModelMixin,DestroyModelMixin): queryset = Student.objects.all() serializer_class = StudentModelSerializer# 6、views.py ModelViewSetfrom rest_framework.viewsets import ModelViewSetclass Book5View(ModelViewSet): #5个接口都有,但是路由有点问题 queryset = Book.objects serializer_class = BookSerializer # urls.py# 使用ModelViewSet编写5个接口 path('books5/', views.Book5View.as_view(actions={'get':'list','post':'create'})), #当路径匹配,又是get请求,会执行Book5View的list方法 re_path('books5/(?Pd+)', views.Book5View.as_view(actions={'get':'retrieve','put':'update','delete':'destroy'})),

Copyright © 2016-2020 www.365daan.com All Rights Reserved. 365答案网 版权所有 备案号:

部分内容来自互联网,版权归原作者所有,如有冒犯请联系我们,我们将在三个工作时内妥善处理。