diff --git a/apps/utils/serializers.py b/apps/utils/serializers.py index ca02634b..c3d128ff 100755 --- a/apps/utils/serializers.py +++ b/apps/utils/serializers.py @@ -39,3 +39,15 @@ class CustomModelSerializer(DynamicFieldsMixin, serializers.ModelSerializer): if hasattr(instance, 'update_by'): validated_data['update_by'] = getattr(self.request, 'user', None) return super().update(instance, validated_data) + +class QuerySerializer(serializers.Serializer): + field = serializers.CharField(label='字段名') + compare = serializers.ChoiceField(label='比较式', choices=["", "!", "gte", "gt", "lte", "lt", "in", "contains"]) + value = serializers.CharField(label='值') + + +class ComplexSerializer(serializers.Serializer): + # page = serializers.IntegerField(min_value=0) + # page_size = serializers.IntegerField(min_value=1) + # query = serializers.CharField(label='获取字段名') + querys = serializers.ListField(child=QuerySerializer(many=True), label="查询列表", required=False) diff --git a/apps/utils/viewsets.py b/apps/utils/viewsets.py index 5161aece..71342dcf 100755 --- a/apps/utils/viewsets.py +++ b/apps/utils/viewsets.py @@ -1,7 +1,7 @@ from django.core.cache import cache from rest_framework.decorators import action -from rest_framework.exceptions import ValidationError +from rest_framework.exceptions import ValidationError, ParseError from rest_framework.mixins import (CreateModelMixin, ListModelMixin, RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin) from rest_framework.permissions import IsAuthenticated, IsAdminUser @@ -13,7 +13,7 @@ from apps.utils.errors import PKS_ERROR from apps.utils.mixins import MyLoggingMixin from apps.utils.permission import ALL_PERMS, RbacPermission, get_user_perms_map from apps.utils.queryset import get_child_queryset2 -from apps.utils.serializers import PkSerializer +from apps.utils.serializers import PkSerializer, ComplexSerializer from rest_framework.throttling import UserRateThrottle @@ -68,7 +68,8 @@ class CustomGenericViewSet(MyLoggingMixin, GenericViewSet): if isinstance(user_perms_map, dict): if hasattr(self, 'perms_map'): perms_map = self.perms_map - action_str = perms_map.get(self.request._request.method.lower(), None) + action_str = perms_map.get( + self.request._request.method.lower(), None) if '*' in perms_map: return queryset elif action_str == '*': @@ -133,6 +134,7 @@ class CustomModelViewSet(CreateModelMixin, UpdateModelMixin, ListModelMixin, """ def __init__(self, **kwargs) -> None: + self.cquery_serializer_class = self.list_serializer_class if self.list_serializer_class else self.serializer_class super().__init__(**kwargs) # 增加默认权限标识 if not self.perms_map: @@ -166,9 +168,46 @@ class CustomModelViewSet(CreateModelMixin, UpdateModelMixin, ListModelMixin, pks = request_data.get('pks', None) if pks: try: - self.get_queryset().model.objects.get_queryset(all=True).filter(id__in=pks).delete(soft=False) + self.get_queryset().model.objects.get_queryset( + all=True).filter(id__in=pks).delete(soft=False) except Exception: self.get_queryset().filter(id__in=pks).delete() return Response(status=204) else: raise ValidationError(**PKS_ERROR) + + @action(methods=['post'], detail=False, perms_map={'post': '*'}, serializer_class=ComplexSerializer) + def cquery(self, request): + """复杂查询 + + 复杂查询 + """ + sr = ComplexSerializer(data=request.data) + sr.is_valid(raise_exception=True) + vdata = sr.validated_data + queryset = self.filter_queryset(self.get_queryset()) + new_qs = queryset.none() + try: + for m in vdata.get('querys', []): + one_qs = queryset + for n in m: + st = {} + if n['compare'] == '!': # 如果是排除比较式 + st[n['field']] = n['value'] + one_qs = one_qs.exclude(**st) + elif n['compare'] == '': + st[n['field']] = n['value'] + one_qs = one_qs.filter(**st) + else: + st[n['field'] + '__' + n['compare']] = n['value'] + one_qs = one_qs.filter(**st) + new_qs = new_qs | one_qs + except Exception as e: + raise ParseError(str(e)) + page = self.paginate_queryset(new_qs) + if page is not None: + serializer = self.cquery_serializer_class(page, many=True) + return self.get_paginated_response(serializer.data) + serializer = self.cquery_serializer_class(new_qs, many=True) + return Response(serializer.data) +