Django基于类的视图(CBV)

Django View

class View:
@classonlymethod
    def as_view(cls, **initkwargs):
        
        def view(request, *args, **kwargs):
            # 实例化,cls为子类
            self = cls(**initkwargs)
            return self.dispatch(request, *args, **kwargs)
        # 返回view,本质和FBV类似
        return view
    

    def dispatch(self, request, *args, **kwargs):
        # get/post/put/patch/delete...
        handler = getattr(self, request.method.lower()
        # 相当于调用get()/post()...
        return handler(request, *args, **kwargs)

DRF APIView

class APIView(View):
    @classmethod
    def as_view(cls, **initkwargs):
        # 调用Django的as_view方法
        view = super().as_view(**initkwargs)
        view.cls = cls
        view.initkwargs = initkwargs
        # 将视图函数标记为不受CSRF视图保护
        return csrf_exempt(view)
    
    def dispatch(self, request, *args, **kwargs):
        self.args = args
        self.kwargs = kwargs
        request = self.initialize_request(request, *args, **kwargs)
        # 此时的request是drf的request
        self.request = request
        # 初始化认证、权限、限流三件套
        self.initial(request, *args, **kwargs)

        # get/post/put/patch/delete...
        handler = getattr(self, request.method.lower(), self.http_method_not_allowed)
        # 相当于调用get()/post()...
        response = handler(request, *args, **kwargs)
        self.response = self.finalize_response(request, response, *args, **kwargs)
        return self.response

DRF GenericAPIView

class GenericAPIView(views.APIView):

    queryset = None
    serializer_class = None
    lookup_field = 'pk'
    lookup_url_kwarg = None

    def get_queryset(self):
        """
        获取queryset
        """
        queryset = self.queryset
        if isinstance(queryset, QuerySet):
            # Ensure queryset is re-evaluated on each request.
            queryset = queryset.all()
        return queryset
    

    def get_object(self):
        """
        获取单个object
        """
        queryset = self.filter_queryset(self.get_queryset())
        # Perform the lookup filtering.
        lookup_url_kwarg = self.lookup_url_kwarg or self.lookup_field

        # 过滤条件,key:默认pk,value:对应的主键值
        filter_kwargs = {self.lookup_field: self.kwargs[lookup_url_kwarg]}
        obj = get_object_or_404(queryset, **filter_kwargs)
        return obj
    
    def get_serializer(self, *args, **kwargs):
        """
        获取序列化器实例
        """
        serializer_class = self.get_serializer_class()
        # 实例化序列化器,instance,data,many
        return serializer_class(*args, **kwargs)
    
    def get_serializer_class(self):
        """
        获取序列化器类
        """
        return self.serializer_class

DRF的各个Mixin, 提取CURD操作的通用逻辑到Mixin

CreateModelMixin 创建

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)
        return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)

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)

RetrieveModelMixin 详情

class RetrieveModelMixin:
    """
    Retrieve a model instance.
    """
    def retrieve(self, request, *args, **kwargs):
        # 和GenericAPIView配合使用,调用GenericAPIView中的方法
        instance = self.get_object()
        # 调用GenericAPIView中的方法
        serializer = self.get_serializer(instance)
        return Response(serializer.data)

UpdateModelMixin 更新


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)
        return Response(serializer.data)

DestroyModelMixin 删除


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

GenericAPIView和各个Mixin再封装

CreateAPIView 创建


class CreateAPIView(mixins.CreateModelMixin,
                    GenericAPIView):
    """
    Concrete view for creating a model instance.
    """
    def post(self, request, *args, **kwargs):
        return self.create(request, *args, **kwargs)

ListAPIView 列表


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

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)

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)

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)

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)


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)

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)


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)

ViewSetMixin


class ViewSetMixin:
    @classonlymethod
    def as_view(cls, actions=None, **initkwargs):
        def view(request, *args, **kwargs):
            self = cls(**initkwargs)
            self.action_map = actions

            # 最关键的循环地方,类似 self.get = get_object,覆盖原有默认的get/post/delete...
            for method, action in actions.items():
                handler = getattr(self, action)
                setattr(self, method, handler)
            return self.dispatch(request, *args, **kwargs)
        return csrf_exempt(view)

ViewSet 在GenericAPIView基础上增加映射机制

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

GenericViewSet 在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

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

注册路由


from rest_framework.routers import DefaultRouter
from .views import BookViewSet

router = DefaultRouter()
router.register(r'books', BookViewSet, basename='book')  # 关键注册方法
urlpatterns = router.urls

自动生成的路由​
image

posted @ 2025-08-28 17:06  xclic  阅读(11)  评论(0)    收藏  举报