前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >DRF视图之重写mixins

DRF视图之重写mixins

原创
作者头像
倔强的数学课代表
修改2023-08-11 17:33:51
2650
修改2023-08-11 17:33:51
举报
文章被收录于专栏:测试开发路漫漫

我们知道,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 属性控制其是否是软删除

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • CreateModelMixin
  • ListModelMixin
  • UpdateModelMixin
  • DestroyModelMixin
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档