五十七、视图组件

一 两个视图基类

1.1 APIView

APIView是所有REST framework提供的所有试图的基类,继承Django的View类。

1.2 GenericAPIView(通用视图类)

类属性:
queryset = None
serializer_class = None
lookup_field = ‘pk’(是get_object方法查询对象时的条件,key=value的形式,key是lookup_field 参数的值,value是路由匹配中的又名分组或者转换器。)
filter_backends(用于queryset过滤的filter后端类)
pagination_class(分页类)

类方法:
get_queryset() # 获取所有要序列化的数据
get_object() #根据pk获取单个数据
get_serializer() # 获取要使用的序列化器,直接使用(调用了get_serializer_class并加括号)
get_serializer_class(return self.serializer_class,拿到的是序列化类)
filter_queryset(过滤相关)
paginate_queryset(分页相关)

1.3 基于APIView写五个接口

from rest_framework.views import APIView
from rest_framework.generics import GenericAPIView
from .serializers import UserSerializers
from .models import User
from rest_framework.response import Response


class UserView(APIView):
    def get(self, request):
        query_set = User.objects.all()
        ser = UserSerializers(instance=query_set, many=True)
        return Response(ser.data)

    def post(self, request):
        ser = UserSerializers(data=request.data)
        if ser.is_valid():
            return Response(ser.data)
        return Response(ser.errors)


class User2View(APIView):
    def get(self, request, pk):
        obj = User.objects.filter(pk=pk).first()
        ser = UserSerializers(instance=obj)
        return Response(ser.data)

    def put(self, request, pk):
        obj = User.objects.filter(pk=pk).first()
        ser = UserSerializers(instance=obj, data=request.data)
        if ser.is_valid():
            return Response(ser.data)
        return Response(ser.errors)

    def delete(self, request, pk):
        User.objects.filter(pk=pk).delete()
        return Response()

1.4 基于GenericAPIView写5个接口

class UserView(GenericAPIView):
    queryset = User.objects.all()
    serializer_class = UserSerializers

    def get(self, request):
        queryset = self.get_queryset()
        ser = self.get_serializer(instance=queryset, 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(ser.data)
        return Response(ser.errors)


class User2View(GenericAPIView):
    queryset = User.objects.all()
    serializer_class = UserSerializers

    def get(self, request):
        obj = self.get_object()
        ser = self.get_serializer(instance=obj)
        return Response(ser.data)

    def put(self, request):
        obj = self.get_object()
        ser = self.get_serializer(instance=obj, data=request.data)
        if ser.is_valid():
            ser.save()
            return Response(ser.data)
        return Response(ser.errors)

    def delete(self, request, pk):
        self.get_queryset().filter(pk=pk).delete()
        return Response('')

练习

1 使用GenericAPIView写出book的5个接口

class BookView(GenericAPIView):
    serializer_class = BookSerializers
    queryset = User.objects.all()

    def get(self, request):
        queryset = self.get_queryset()
        ser = self.get_serializer(instance=queryset, 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(ser.data)
        return Response(ser.errors)


class Book2View(GenericAPIView):
    queryset = Book.objects.all()
    serializer_class = BookSerializers

    def get(self, request):
        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(ser.data)
        return Response(ser.errors)

    def delete(self, request, pk):
        self.get_queryset().filter(pk=pk).delete()
        return Response('')

2 使用面向对象,写5个父类, 继承GenericAPIView+某几个父类后,就有某几个接口
新增1条
GenericAPIView+Create

class GetAll:
    def get(self, request):
        print(self.__dict__)
        queryset = self.get_queryset()
        ser = self.get_serializer(instance=queryset, many=True)
        return Response(ser.data)


class GetOne:
    def get(self, request, pk):
        obj = self.get_object()
        ser = self.get_serializer(instance=obj)
        return Response(ser.data)


class Create:
    def post(self, request):
        ser = self.get_serializer(data=request.data)
        if ser.is_valid():
            ser.save()
            return Response(ser.data)
        return Response(ser.errors)


class Alter:
    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(ser.data)
        return Response(ser.errors)


class Delete:
    def delete(self, request, pk):
        self.get_queryset().filter(pk=pk).delete()
        return Response()


class BookView(GenericAPIView, GetAll, Create):
    queryset = Book.objects.all()
    serializer_class = BookSerializers


class Book2View(GenericAPIView, GetOne, Alter, Delete):
    queryset = Book.objects.all()
    serializer_class = BookSerializers

3 9个视图子类

class GetAll(GenericAPIView):
    def get(self, request):
        print(self.__dict__)
        queryset = self.get_queryset()
        ser = self.get_serializer(instance=queryset, many=True)
        return Response(ser.data)


class GetOne(GenericAPIView):
    def get(self, request, pk):
        obj = self.get_object()
        ser = self.get_serializer(instance=obj)
        return Response(ser.data)


class Create(GenericAPIView):
    def post(self, request):
        ser = self.get_serializer(data=request.data)
        if ser.is_valid():
            ser.save()
            return Response(ser.data)
        return Response(ser.errors)


class Alter(GenericAPIView):
    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(ser.data)
        return Response(ser.errors)


class Delete(GenericAPIView):
    def delete(self, request, pk):
        self.get_queryset().filter(pk=pk).delete()
        return Response()


class A(GetAll):
    pass


class B(Create):
    pass


class C(GetOne):
    pass


class D(Alter):
    pass


class E(Delete):
    pass


class F(GetAll, Create):
    pass


class G(GetOne, Alter):
    pass


class H(Alter, Delete):
    pass


class J(Delete):
    pass


class I(GetOne, Alter, Delete):
    pass


class BookView(A):
    queryset = Book.objects.all()
    serializer_class = BookSerializers


class Book2View(G):
    queryset = Book.objects.all()
    serializer_class = BookSerializers

二 五个视图扩展类

2.1 ListModelMixin

类中有一个list方法,就是上面写的基于GenericAPIView写的五个接口中的get获取全部。

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)

2.2 CreateModelMixin

类中有一个create方法,就是上面写的基于GenericAPIView写的五个接口中的post。

class CreateModelMixin:
    """
    Create a model instance.
    """
    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)

    def perform_create(self, serializer):
        serializer.save()

    def get_success_headers(self, data):
        try:
            return {'Location': str(data[api_settings.URL_FIELD_NAME])}
        except (TypeError, KeyError):
            return {}

2.3 RetrieveModelMixin

类中有一个retrieve方法,就是上边写的基于GenericAPIView写的get方法获取单条数据。

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)

2.4 UpdateModelMixin

类中有一个update方法,就是上边写的基于GenericAPIView写的put方法修改一条数据。

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)

2.5 DestroyModelMixin

类中有一个destroy方法,就是上边写的基于GenericAPIView写的delete方法。

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()

2.6 基于GenericAPIView和五个视图扩展类写接口

因为五个视图扩展类用到了GenericAPIView类中的属性和方法,所以必须结合GenericAPIView一起使用。

需要什么功能就继承GenericAPIView和试图扩展类

from rest_framework.Mixins import ListModelMixin, CreateModelMixin, RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin
class UserView(GenericAPIView, ListModelMixin, CreateModelMixin):
    queryset = User.objects  # 可以加.all(),也可以不用加,get_queryset方法会自动加
    serializer_class = UserSerializers

    def get(self, request, *args, **kwargs):
        return self.list(request, *args, **kwargs)

    def post(self, request, *args, **kwargs):
        return self.create(request, *args, **kwargs)


class User2View(GenericAPIView, RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin):
    queryset = User.objects  # 可以加.all(),也可以不用加,get_queryset方法会自动加
    serializer_class = UserSerializers

    def get(self, request, *args, **kwargs):
        return self.retrieve(request, *args, **kwargs)

    def put(self, request, *args, **kwargs):
        return self.update(request, *args, **kwargs)

    def delete(self, request, *args, **kwargs):
        return self.destroy(request, *args, **kwargs)

三 九个视图子类

from rest_framework.generics import ListAPIView, CreateAPIView, RetrieveAPIView, UpdateAPIView, DestroyAPIView, \
    ListCreateAPIView, RetrieveUpdateDestroyAPIView, RetrieveUpdateAPIView, RetrieveDestroyAPIView

3.1 ListAPIView

class ListAPIView(mixins.ListModelMixin,
                  GenericAPIView):
    """
    Concrete view for listing a queryset.
    """
    def get(self, request, *args, **kwargs):
        return self.list(request, *args, **kwargs)

3.2 CreateAPIView

class CreateAPIView(mixins.CreateModelMixin,
                  GenericAPIView):
    """
    Concrete view for listing a queryset.
    """
    def get(self, request, *args, **kwargs):
        return self.create(request, *args, **kwargs)

3.3 RetrieveAPIView

class RetrieveAPIView(mixins.RetrieveModelMixin,
                      GenericAPIView):
    """
    Concrete view for retrieving a model instance.
    """
    def get(self, request, *args, **kwargs):
        return self.retrieve(request, *args, **kwargs)

3.4 UpdateAPIView

class UpdateAPIView(mixins.UpdateModelMixin,
                    GenericAPIView):
    """
    Concrete view for updating a model instance.
    """
    def put(self, request, *args, **kwargs):
        return self.update(request, *args, **kwargs)

    def patch(self, request, *args, **kwargs):
        return self.partial_update(request, *args, **kwargs)

3.5 DestroyAPIView

class DestroyAPIView(mixins.DestroyModelMixin,
                     GenericAPIView):
    """
    Concrete view for deleting a model instance.
    """
    def delete(self, request, *args, **kwargs):
        return self.destroy(request, *args, **kwargs)

3.6 ListCreateAPIView

class ListCreateAPIView(mixins.ListModelMixin,
                        mixins.CreateModelMixin,
                        GenericAPIView):
    """
    Concrete view for listing a queryset or creating a model instance.
    """
    def get(self, request, *args, **kwargs):
        return self.list(request, *args, **kwargs)

    def post(self, request, *args, **kwargs):
        return self.create(request, *args, **kwargs)

3.7 RetrieveUpdateAPIView

class RetrieveUpdateAPIView(mixins.RetrieveModelMixin,
                            mixins.UpdateModelMixin,
                            GenericAPIView):
    """
    Concrete view for retrieving, updating a model instance.
    """
    def get(self, request, *args, **kwargs):
        return self.retrieve(request, *args, **kwargs)

    def put(self, request, *args, **kwargs):
        return self.update(request, *args, **kwargs)

    def patch(self, request, *args, **kwargs):
        return self.partial_update(request, *args, **kwargs)

3.8 RetrieveDestroyAPIView

class RetrieveDestroyAPIView(mixins.RetrieveModelMixin,
                             mixins.DestroyModelMixin,
                             GenericAPIView):
    """
    Concrete view for retrieving or deleting a model instance.
    """
    def get(self, request, *args, **kwargs):
        return self.retrieve(request, *args, **kwargs)

    def delete(self, request, *args, **kwargs):
        return self.destroy(request, *args, **kwargs)

3.9 RetrieveUpdateDestroyAPIView

class RetrieveUpdateDestroyAPIView(mixins.RetrieveModelMixin,
                                   mixins.UpdateModelMixin,
                                   mixins.DestroyModelMixin,
                                   GenericAPIView):
    """
    Concrete view for retrieving, updating or deleting a model instance.
    """
    def get(self, request, *args, **kwargs):
        return self.retrieve(request, *args, **kwargs)

    def put(self, request, *args, **kwargs):
        return self.update(request, *args, **kwargs)

    def patch(self, request, *args, **kwargs):
        return self.partial_update(request, *args, **kwargs)

    def delete(self, request, *args, **kwargs):
        return self.destroy(request, *args, **kwargs)

3.10 基于九个视图子类写接口

class UserView(ListAPIView):
    queryset = User.objects
    serializer_class = UserSerializers


class User2View(RetrieveAPIView):
    queryset = User.objects
    serializer_class = UserSerializers

四 视图集

4.1 ViewsetMixin

重写了as_view方法,只要继承了ViewsetMixin就必须在as_view中传actions参数,以字典的形式,key值是请求方式,value是方法名。

class ViewSetMixin:
                            
    @classonlymethod
    # ViewsetMixin的as_view
    def as_view(cls, actions=None, **initkwargs):
    	# actions参数不能为空
    	# actions = {'get': 'list', 'post':'create'}
        if not actions:
            raise TypeError("The `actions` argument must be provided when "
                            "calling `.as_view()` on a ViewSet. For example "
                            "`.as_view({'get': 'list'})`")
                            
		# 当路由匹配成功会执行view
        def view(request, *args, **kwargs):
			# method = get
			# action = list
            for method, action in actions.items():
            	# 反射 视图类的对象找'list'方法
            	# 如果继承了五个视图基类 就可以找到list方法
                handler = getattr(self, action)
                # 给对象设置属性
                self.get = 视图基类的list方法
                setattr(self, method, handler)
			# 执行dispatch 是APIView里的dispatch
            return self.dispatch(request, *args, **kwargs)

        return csrf_exempt(view)

4.2 ViewSet

继承了ViewSetMixin和APIView

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

4.3 GenericViewSet

继承了ViewSetMixin和GenericAPIView

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

4.3 ModelViewSet

继承了五个视图扩展类和GenericViewSet

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

4.4 ReadOnlyModelViewSet

继承了ListModelMixin、RetrieveModelMixin和GenericViewSet

class ReadOnlyModelViewSet(mixins.RetrieveModelMixin,
                           mixins.ListModelMixin,
                           GenericViewSet):
    """
    A viewset that provides default `list()` and `retrieve()` actions.
    """
    pass

4.5 基于ModelViewSet写接口

from rest_framework.viewsets import ViewSetMixin, ViewSet, GenericViewSet, ModelViewSet, ReadOnlyModelViewSet
class UserView(ModelViewSet):
    queryset = User.objects
    serializer_class = UserSerializers

路由必须传actions参数

path('users/', views.UserView.as_view({'get': 'list', 'post':'create'})),
path('users/<int:pk>/', views.UserView.as_view({'get': 'retrieve', 'put': 'update', 'delete': 'destroy'})),

继承关系图
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值