DRF视图之重写mixins

2023-08-11 17:33:51 浏览数 (2)

我们知道,DRF视图体系,封装程度最高的是ModelViewSet,它集增删改查的mixinsGenericViewSet于一体。

代码语言:Python复制
class ModelViewSet(mixins.CreateModelMixin,
                   mixins.RetrieveModelMixin,
                   mixins.UpdateModelMixin,
                   mixins.DestroyModelMixin,
                   mixins.ListModelMixin,
                   GenericViewSet):
        pass

所以,业务视图类只要继承它就能实现增删改查的功能,然而,正是由于它的抽象性太高,一些定制化的功能无法实现,所以大多数情况下,我们选择重写ModelViewSet,但ModelViewSet又只是一个空壳,重写他就是重写他集成的类的功能,这里我们先重写这些mixins

CreateModelMixin

代码语言:Python复制
class CreateModelMixin:
    """
    Create a model instance.
    """

    def create(self, request, *args, **kwargs):
        if not isinstance(request.user, AnonymousUser):
            request.data['created_by'] = request.user.get('id')
            request.data['updated_by'] = request.user.get('id')
        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):
        try:
            with transaction.atomic():
                serializer.save()
        except Exception as e:
            raise ValidationError({'msg': str(e)})

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

增加功能:

  • 新建数据时,为created_by赋值当前请求发送者信息
  • 新建数据时,为 updated_by 赋值当前请求发送者信息

ListModelMixin

代码语言:Python复制
class ListModelMixin:
    """
    List a queryset.
    """

    def list(self, request, *args, **kwargs):
        use_pagination = request.query_params.get('use_pagination', True)  # 如果禁用分页,传参use_pagination=False
        queryset = self.filter_queryset(self.get_queryset())
        if use_pagination:
            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)

增加功能:

  • URL查询参数增加use_pagination查询,用于控制是否启用分页

UpdateModelMixin

代码语言:Python复制
class UpdateModelMixin:
    """
    Update a model instance.
    """

    def update(self, request, *args, **kwargs):
        partial = kwargs.pop('partial', False)
        if not isinstance(request.user, AnonymousUser):
            request.data['updated_by'] = request.user.get('id')
        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):
        try:
            with transaction.atomic():
                serializer.save()
        except Exception as e:
            raise ValidationError({'msg': str(e)})

    def partial_update(self, request, *args, **kwargs):
        kwargs['partial'] = True
        return self.update(request, *args, **kwargs)
  • 更新数据时,为 updated_by 赋值当前请求发送者信息

DestroyModelMixin

代码语言:Python复制
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):
        # 逻辑删除
        filter_active = getattr(self, 'filter_active', True)
        try:
            with transaction.atomic():
                if filter_active:
                    instance.is_deleted = True
                    instance.save()
                else:
                    instance.delete()
        except Exception as e:
            raise ValidationError({'msg': str(e)})
  • 删除时,按照视图类是否有配置filter_active 属性控制其是否是软删除

0 人点赞