Django REST Framework 之视图梳理APIView、GenericViewSet、ModelViewSet(超详细)

53 篇文章 0 订阅

APIView

DRF 为了更符合 restful api 规范,在 View 上层做了一层封装,就是 APIView,View 本身没有权限和认证以及限流等的操作,只做请求的分发,然后返回,里面就是一些简单的分发逻辑,但APIView不同,重写了 as_view方法,里面做了认证、限流、权限、渲染很多东西。
这种视图还不够通用,需要自己写一些分页、序列化、queryset 之类的东西。

class APIView(View):

    # The following policies may be set at either globally, or per-view.
    renderer_classes = api_settings.DEFAULT_RENDERER_CLASSES
    parser_classes = api_settings.DEFAULT_PARSER_CLASSES
    authentication_classes = api_settings.DEFAULT_AUTHENTICATION_CLASSES
    throttle_classes = api_settings.DEFAULT_THROTTLE_CLASSES
    permission_classes = api_settings.DEFAULT_PERMISSION_CLASSES
    content_negotiation_class = api_settings.DEFAULT_CONTENT_NEGOTIATION_CLASS
    metadata_class = api_settings.DEFAULT_METADATA_CLASS
    versioning_class = api_settings.DEFAULT_VERSIONING_CLASS

ViewSet

他继承了 APIView和ViewSetMIxin, 他接收一个 action 关键字参数,作为覆盖 .as_view() 以便它接受一个 actions 关键字,该关键字将 HTTP 方法绑定到资源上的操作。
url 要这样写:MyViewSet.as_view({'get': 'list', 'post': 'create'})
这种视图一般不怎么常用,url 这样写看起来也不太好看,不优雅。

class ViewSet(ViewSetMixin, views.APIView):
    """
    The base ViewSet class does not provide any actions by default.
    """
    pass

class ViewSetMixin:
    """
    This is the magic.

    Overrides `.as_view()` so that it takes an `actions` keyword that performs
    the binding of HTTP methods to actions on the Resource.

    For example, to create a concrete view binding the 'GET' and 'POST' methods
    to the 'list' and 'create' actions...

    view = MyViewSet.as_view({'get': 'list', 'post': 'create'})
    """

class UserViewSet(viewsets.ViewSet):
    """
    A simple ViewSet for listing or retrieving users.
    """
    def list(self, request):
        queryset = User.objects.all()
        serializer = UserSerializer(queryset, many=True)
        return Response(serializer.data)

    def retrieve(self, request, pk=None):
        queryset = User.objects.all()
        user = get_object_or_404(queryset, pk=pk)
        serializer = UserSerializer(user)
        return Response(serializer.data)

可以这样写:
	from myapp.views import UserViewSet
	from rest_framework.routers import DefaultRouter
	
	router = DefaultRouter()
	router.register(r'users', UserViewSet)
	urlpatterns = router.urls

也可以这样:
	UserViewSet.as_view({'get': 'list'})
	UserViewSet.as_view({'get': 'retrieve'})

GenericViewSet

这个比上述两个要好一点,里面做了很多封装,如获取对象的、序列化的、分页的、queryset 等一系列操作,只需要指定好,在接口里面使用提供好的方法就行。
一般比较常用,封装了很多常用的内容。

class 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.
    """
    pass


class GenericAPIView(views.APIView):
    """
    Base class for all other generic views.
    """
    # You'll need to either set these attributes,
    # or override `get_queryset()`/`get_serializer_class()`.
    # If you are overriding a view method, it is important that you call
    # `get_queryset()` instead of accessing the `queryset` property directly,
    # as `queryset` will get evaluated only once, and those results are cached
    # for all subsequent requests.
    # queryset
    queryset = None
    # 序列化
    serializer_class = None

    # If you want to use object lookups other than pk, set 'lookup_field'.
    # For more complex lookup requirements override `get_object()`.
    lookup_field = 'pk'
    lookup_url_kwarg = None

    # The filter backend classes to use for queryset filtering
    # 过滤器
    filter_backends = api_settings.DEFAULT_FILTER_BACKENDS

    # The style to use for queryset pagination.
    # 分页
    pagination_class = api_settings.DEFAULT_PAGINATION_CLASS

提供方法:
	get_queryset:获取集合
	get_object:获取一个model对象
	get_serializer:获取序列化器
	filter_queryset:筛选之后的queryset
	paginate_queryset:处理queryset
	get_paginated_response:返回分页结构的response
	

class UserGenericViewSet(GenericViewSet):
    queryset = User.objects.all()
    serializer_class = UserSerializer
    parser_classes = PageNumberPagination
	
	def post(self, request, *args, **kwargs):
        users = self.queryset()
        ser = self.get_serializer()
        return Response(ser.data)

mixins

提供了列表方法、创建、删除、获取、更新的方法,如果你这个功能只实现一个接口,如只有一个列表,直接继承list方法就行
这种只针对某一个模块有很少的功能时,可以采用

from rest_framework.mixins import 
ListModelMixin, CreateModelMixin, RetrieveModelMixin, 
UpdateModelMixin, DestroyModelMixin

class UserList(ListModelMixin):
    queryset = User.objects.all()
    serializer_class = UserSerializer
    parser_classes = PageNumberPagination

ModelViewSet

提供了增删改查四个方法,只需要定义好序列化,集合、分页器就好。
适合大模块,增删改查都有的,可以使用这个视图

class 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

# 四个方法都有了,包括局部更新 patch, 工6个方法,还支持重写,完成自己想要的功能
class UserGenericViewSet(ModelViewSet):
     queryset = User.objects.all()
	 serializer_class = UserSerializer
     parser_classes = PageNumberPagination

总结

  1. apiview:提供了基础设施,增加了权限、认证、限流等相关功能,为扩展视图类提供了坚硬的基础,也可以在这个视图里面实现一些简单的接口,但不那么通用
  2. ViewSet:url 提供了action 关键字传参的方式,指定获取那个方法,不那么实用
  3. GenericViewSet:通用视图类,封装了集合、序列化、分页、筛选等操作,比较常用
  4. mixins:支持简单的增删改查操作,某个模块只有一个接口时,可以采用
  5. ModelViewSet:封装了增删改查四个方法,适合完整的大功能。

参考文献

django rest framework 中文网:https://q1mi.github.io/Django-REST-framework-documentation/
django rest framework 源码:https://blog.csdn.net/qq_39253370/article/details/124690671?spm=1001.2014.3001.5501

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
好的,下面是基于Djangorest_framework框架的ModelViewSet视图的源码解析: 1.基本介绍 ModelViewSet视图Django框架的rest_framework模块中的一个视图类,它继承了GenericAPIView和Mixins,提供了对资源的CRUD操作。ModelViewSet视图类中提供了一系列的方法,如list、create、retrieve、update、partial_update、destroy等,这些方法对应着HTTP请求中的GET、POST、PUT、PATCH、DELETE等动词。 2.源码解析 ModelViewSet视图的源码主要涉及到以下几个部分: (1)视图类的定义 ``` class 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 ``` 从源码可以看出,ModelViewSet继承了CreateModelMixin、RetrieveModelMixin、UpdateModelMixin、DestroyModelMixin和ListModelMixin这些视图混合类,以及GenericViewSet类。 (2)视图方法的实现 a. list方法 ``` 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) ``` list方法用于返回资源列表,它首先通过get_queryset方法获取查询集,然后通过filter_queryset方法对查询集进行过滤,最后通过get_serializer方法将查询集序列化为JSON数据返回给客户端。 b. create方法 ``` def create(self, request, *args, **kwargs): serializer = self.get_serializer(data=request.data) serializer.is_valid(raise_exception=True) self.perform_create(serializer) headers = self.get_success_headers(serializer.data) return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers) ``` create方法用于创建资源,它首先通过get_serializer方法获取序列化器,然后通过perform_create方法进行资源的创建,最后返回HTTP 201 Created状态码以及资源的JSON数据。 c. retrieve方法 ``` def retrieve(self, request, *args, **kwargs): instance = self.get_object() serializer = self.get_serializer(instance) return Response(serializer.data) ``` retrieve方法用于获取单个资源,它通过get_object方法获取资源实例,然后通过get_serializer方法将资源实例序列化为JSON数据返回给客户端。 d. update方法 ``` 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) return Response(serializer.data) ``` update方法用于更新资源,它首先通过get_object方法获取资源实例,然后通过get_serializer方法获取序列化器,最后通过perform_update方法进行资源的更新,最终返回更新后的资源JSON数据。 e. partial_update方法 ``` def partial_update(self, request, *args, **kwargs): kwargs['partial'] = True return self.update(request, *args, **kwargs) ``` partial_update方法用于部分更新资源,它通过调用update方法,并将partial参数设置为True,进行资源的部分更新。 f. destroy方法 ``` def destroy(self, request, *args, **kwargs): instance = self.get_object() self.perform_destroy(instance) return Response(status=status.HTTP_204_NO_CONTENT) ``` destroy方法用于删除资源,它首先通过get_object方法获取资源实例,然后通过perform_destroy方法进行资源的删除,最终返回HTTP 204 No Content状态码。 3.总结 ModelViewSet视图Django框架的rest_framework模块中的一个视图类,它继承了GenericAPIView和Mixins,提供了对资源的CRUD操作。通过对视图类的源码解析,我们可以深入了解ModelViewSet视图的内部实现,从而更好地理解和使用该视图类。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值