Loading

23.mixin类源码解析

mixin类用于提供视图的基本操作行为,注意mixin类提供动作方法,而不是直接定义处理程序方法
例如.get() .post(),这允许更灵活的定义,mixin从rest_framework.mixins导入
mixin只是提供了基本操作行为,并没有queryset、get_object()等属性方法,所以我们使用mixin的时候,
要同时继承GenericAPIView配合使用
CreateModelMixin
"""
提供 .create(request, *args, **kwargs) 方法,实现创建和保存一个新model实例的功能。
如果创建了一个对象,这将返回一个 201 Created 响应,将该对象的序列化表示作为响应的
主体。如果序列化的表示中包含名为 url 的键,则响应的 Location 头将填充该值。
如果为创建对象提供的请求数据无效,将返回 400 Bad Request ,其中错误详细信息作为响应的正文。
"""
#源码
class CreateModelMixin:
    """
    Create a model instance.
    """
    def create(self, request, *args, **kwargs):
        #序列化数据
        serializer = self.get_serializer(data=request.data)
        #is_valid判断序列化是否数据是否有效,raise_exception=Teue有问题自动抛出错误
        serializer.is_valid(raise_exception=True)
        # 调用下方方法保存数据
        self.perform_create(serializer)
        # 成功的headers
        headers = self.get_success_headers(serializer.data)
        return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)

    
    def perform_create(self, serializer):
        """
        单独写一个函数调用.save,这样写的意义是后续保存前需要做其他事情,
        直接重写该方法就可以
        """
        serializer.save()
    
    def get_success_headers(self, data):
        try:
            return {'Location': str(data[api_settings.URL_FIELD_NAME])}
        except (TypeError, KeyError):
            return {}
ListModelMixin
"""
提供一个 .list(request, *args, **kwargs) 方法,返回查询结果的列表。
如果查询集被填充了数据,则返回 200 OK 响应,将查询集的序列化表示作为响应的主体。
相应数据可以任意分页。
"""
#源码
class ListModelMixin:
    """
    List a queryset.
    """
    def list(self, request, *args, **kwargs):
        """
        self.get_queryset() 获取查询结果集
        self.filter_queryset() 留了一个钩子,如果有需要,可以过滤结果集
        """
        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
"""
提供一个 .retrieve(request, *args, **kwargs) 方法,返回响应中现有模型的实例。
如果可以检索对象,则返回 200 OK 响应,将该对象的序列化表示作为响应的主体。否则将
返回 404 Not Found 。
"""
#源码
class RetrieveModelMixin:
    """
    Retrieve a model instance.
    """
    def retrieve(self, request, *args, **kwargs):
        # 获取指定look_up_field查询的内容
        instance = self.get_object()
        # 序列化数据
        serializer = self.get_serializer(instance)
        return Response(serializer.data)
UpdateModelMixin
"""
提供 .update(request, *args, **kwargs) 方法,实现更新和保存现有模型实例的功能
同时还提供了一个 .partial_update(request, *args, **kwargs) 方法,这个方法
和 update 方法类似,但更新的所有字段都是可选的。这允许支持 HTTP PATCH 请求。
如果一个对象被更新,这将返回一个 200 OK 响应,并将对象的序列化表示作为响应的主体。
如果为更新对象提供的请求数据无效,将返回一个 400 Bad Request 响应,错误详细信息作为响应的正文。
"""
#源码
class UpdateModelMixin:
    """
    Update a model instance.
    """
    
    def update(self, request, *args, **kwargs):
        partial = kwargs.pop('partial', False)
        # 查询指定的lookup_filed结果
        instance = self.get_object()
        
        serializer = self.get_serializer(instance, data=request.data, partial=partial)
        serializer.is_valid(raise_ex ception=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)
DestroyModelMixin
"""
提供一个 .destroy(request, *args, **kwargs) 方法,实现删除现有模型实例的功能。
如果成功删除对象,则返回 204 No Content 响应,否则返回 404 Not Found 。
DRF对mixin类的设计是让它们可以尽量的组合使用,不是一次只能继承一个mixin,可以同时继承多个mixin
"""
#源码
class DestroyModelMixin:
    """
    Destroy a model instance.
    """
    def destroy(self, request, *args, **kwargs):
        # 查询指定的lookup_filed结果
        instance = self.get_object()
        # 删除指定数据
        self.perform_destroy(instance)
        return Response(status=status.HTTP_204_NO_CONTENT)

    def perform_destroy(self, instance):
        # 删除前需要其他操作的话,可以重写该方法
        instance.delete()

posted @ 2022-07-21 19:33  木子七  阅读(76)  评论(0编辑  收藏  举报