feat: utils增加批量接口mixin
This commit is contained in:
parent
388d9213fd
commit
0f1bb7fd72
|
@ -8,6 +8,13 @@ from django.db import connection
|
||||||
from django.utils.timezone import now
|
from django.utils.timezone import now
|
||||||
from user_agents import parse
|
from user_agents import parse
|
||||||
import logging
|
import logging
|
||||||
|
from rest_framework.response import Response
|
||||||
|
from django.db import transaction
|
||||||
|
from rest_framework.exceptions import ParseError, ValidationError
|
||||||
|
from apps.utils.errors import PKS_ERROR
|
||||||
|
from rest_framework.generics import get_object_or_404
|
||||||
|
from drf_yasg.utils import swagger_auto_schema
|
||||||
|
from apps.utils.serializers import PkSerializer
|
||||||
|
|
||||||
# 实例化myLogger
|
# 实例化myLogger
|
||||||
myLogger = logging.getLogger('log')
|
myLogger = logging.getLogger('log')
|
||||||
|
@ -66,6 +73,105 @@ class CustomUpdateModelMixin(UpdateModelMixin):
|
||||||
serializer.save(update_by=self.request.user)
|
serializer.save(update_by=self.request.user)
|
||||||
|
|
||||||
|
|
||||||
|
class BulkCreateModelMixin(CreateModelMixin):
|
||||||
|
|
||||||
|
def after_bulk_create(self, objs):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def create(self, request, *args, **kwargs):
|
||||||
|
"""创建(支持批量)
|
||||||
|
|
||||||
|
创建(支持批量)
|
||||||
|
"""
|
||||||
|
rdata = request.data
|
||||||
|
many = False
|
||||||
|
if isinstance(rdata, list):
|
||||||
|
many = True
|
||||||
|
with transaction.atomic():
|
||||||
|
sr = self.get_serializer(rdata, many=many)
|
||||||
|
sr.is_valid(raise_exception=True)
|
||||||
|
self.perform_create(sr)
|
||||||
|
if many:
|
||||||
|
self.after_bulk_create(sr.data)
|
||||||
|
return Response(sr.data, status=201)
|
||||||
|
|
||||||
|
|
||||||
|
class BulkUpdateModelMixin(UpdateModelMixin):
|
||||||
|
|
||||||
|
def after_bulk_update(self, objs):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def partial_update(self, request, *args, **kwargs):
|
||||||
|
"""部分更新(支持批量)
|
||||||
|
|
||||||
|
部分更新(支持批量)
|
||||||
|
"""
|
||||||
|
kwargs['partial'] = True
|
||||||
|
return self.update(request, *args, **kwargs)
|
||||||
|
|
||||||
|
def update(self, request, *args, **kwargs):
|
||||||
|
"""更新(支持批量)
|
||||||
|
|
||||||
|
更新(支持批量)
|
||||||
|
"""
|
||||||
|
partial = kwargs.pop('partial', False)
|
||||||
|
lookup_url_kwarg = self.lookup_url_kwarg or self.lookup_field
|
||||||
|
if kwargs[lookup_url_kwarg] == 'bulk': # 如果是批量操作
|
||||||
|
queryset = self.filter_queryset(self.get_queryset())
|
||||||
|
objs = []
|
||||||
|
if isinstance(request.data, list):
|
||||||
|
with transaction.atomic():
|
||||||
|
for ind, item in enumerate(request.data):
|
||||||
|
obj = get_object_or_404(queryset, id=item['id'])
|
||||||
|
sr = self.get_serializer(obj, data=item, partial=partial)
|
||||||
|
if not sr.is_valid():
|
||||||
|
err_dict = { f'第{ind+1}': sr.errors}
|
||||||
|
raise ValidationError(err_dict)
|
||||||
|
self.perform_update(sr) # 用自带的更新,可能需要做其他操作
|
||||||
|
objs.append(sr.data)
|
||||||
|
self.after_bulk_update(objs)
|
||||||
|
else:
|
||||||
|
raise ParseError('提交数据非列表')
|
||||||
|
return Response(objs)
|
||||||
|
else:
|
||||||
|
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)
|
||||||
|
|
||||||
|
|
||||||
|
class BulkDestroyModelMixin(DestroyModelMixin):
|
||||||
|
|
||||||
|
@swagger_auto_schema(request_body=PkSerializer)
|
||||||
|
def destroy(self, request, *args, **kwargs):
|
||||||
|
"""删除(支持批量)
|
||||||
|
|
||||||
|
删除(支持批量和硬删除(需管理员权限))
|
||||||
|
"""
|
||||||
|
lookup_url_kwarg = self.lookup_url_kwarg or self.lookup_field
|
||||||
|
if kwargs[lookup_url_kwarg] == 'bulk': # 如果是批量操作
|
||||||
|
queryset = self.filter_queryset(self.get_queryset())
|
||||||
|
ids = request.data.get('ids', None)
|
||||||
|
soft = request.data.get('soft', True)
|
||||||
|
if ids:
|
||||||
|
if soft is True:
|
||||||
|
queryset.filter(id__in=ids).delete()
|
||||||
|
elif soft is False:
|
||||||
|
try:
|
||||||
|
queryset.model.objects.get_queryset(
|
||||||
|
all=True).filter(id__in=ids).delete(soft=False)
|
||||||
|
except Exception:
|
||||||
|
queryset.filter(id__in=ids).delete()
|
||||||
|
return Response(status=204)
|
||||||
|
else:
|
||||||
|
raise ValidationError(**PKS_ERROR)
|
||||||
|
else:
|
||||||
|
instance = self.get_object()
|
||||||
|
self.perform_destroy(instance)
|
||||||
|
return Response(status=204)
|
||||||
|
|
||||||
|
|
||||||
class MyLoggingMixin(object):
|
class MyLoggingMixin(object):
|
||||||
"""Mixin to log requests"""
|
"""Mixin to log requests"""
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,8 @@ from rest_framework.request import Request
|
||||||
|
|
||||||
|
|
||||||
class PkSerializer(serializers.Serializer):
|
class PkSerializer(serializers.Serializer):
|
||||||
pks = serializers.ListField(child=serializers.CharField(max_length=20), label="主键ID列表")
|
ids = serializers.ListField(child=serializers.CharField(max_length=20), label="主键ID列表")
|
||||||
|
soft = serializers.BooleanField(label="是否软删除", default=True, required=False)
|
||||||
|
|
||||||
|
|
||||||
class GenSignatureSerializer(serializers.Serializer):
|
class GenSignatureSerializer(serializers.Serializer):
|
||||||
|
|
|
@ -10,14 +10,16 @@ from rest_framework.viewsets import GenericViewSet
|
||||||
|
|
||||||
from apps.system.models import DataFilter, Dept, User
|
from apps.system.models import DataFilter, Dept, User
|
||||||
from apps.utils.errors import PKS_ERROR
|
from apps.utils.errors import PKS_ERROR
|
||||||
from apps.utils.mixins import MyLoggingMixin
|
from apps.utils.mixins import MyLoggingMixin, BulkCreateModelMixin, BulkUpdateModelMixin, BulkDestroyModelMixin
|
||||||
from apps.utils.permission import ALL_PERMS, RbacPermission, get_user_perms_map
|
from apps.utils.permission import ALL_PERMS, RbacPermission, get_user_perms_map
|
||||||
from apps.utils.queryset import get_child_queryset2
|
from apps.utils.queryset import get_child_queryset2
|
||||||
from apps.utils.serializers import PkSerializer, ComplexSerializer
|
from apps.utils.serializers import PkSerializer, ComplexSerializer
|
||||||
from rest_framework.throttling import UserRateThrottle
|
from rest_framework.throttling import UserRateThrottle
|
||||||
from drf_yasg.utils import swagger_auto_schema
|
from drf_yasg.utils import swagger_auto_schema
|
||||||
from apps.utils.decorators import idempotent
|
from apps.utils.decorators import idempotent
|
||||||
|
from django.db import transaction
|
||||||
import json
|
import json
|
||||||
|
from rest_framework.generics import get_object_or_404
|
||||||
|
|
||||||
|
|
||||||
class CustomGenericViewSet(MyLoggingMixin, GenericViewSet):
|
class CustomGenericViewSet(MyLoggingMixin, GenericViewSet):
|
||||||
|
@ -157,8 +159,8 @@ class CustomGenericViewSet(MyLoggingMixin, GenericViewSet):
|
||||||
return queryset.filter(create_by=self.request.user)
|
return queryset.filter(create_by=self.request.user)
|
||||||
|
|
||||||
|
|
||||||
class CustomModelViewSet(CreateModelMixin, UpdateModelMixin, ListModelMixin,
|
class CustomModelViewSet(BulkCreateModelMixin, BulkUpdateModelMixin, ListModelMixin,
|
||||||
RetrieveModelMixin, DestroyModelMixin, CustomGenericViewSet):
|
RetrieveModelMixin, BulkDestroyModelMixin, CustomGenericViewSet):
|
||||||
"""
|
"""
|
||||||
增强的ModelViewSet
|
增强的ModelViewSet
|
||||||
"""
|
"""
|
||||||
|
@ -173,41 +175,6 @@ class CustomModelViewSet(CreateModelMixin, UpdateModelMixin, ListModelMixin,
|
||||||
if v not in ALL_PERMS and v != '*':
|
if v not in ALL_PERMS and v != '*':
|
||||||
ALL_PERMS.append(v)
|
ALL_PERMS.append(v)
|
||||||
|
|
||||||
# @idempotent()
|
|
||||||
# def create(self, request, *args, **kwargs):
|
|
||||||
# return super().create(request, *args, **kwargs)
|
|
||||||
|
|
||||||
@action(methods=['post'], detail=False, serializer_class=PkSerializer)
|
|
||||||
def deletes(self, request, *args, **kwargs):
|
|
||||||
"""
|
|
||||||
批量删除
|
|
||||||
"""
|
|
||||||
request_data = request.data
|
|
||||||
pks = request_data.get('pks', None)
|
|
||||||
if pks:
|
|
||||||
self.get_queryset().filter(id__in=pks).delete()
|
|
||||||
return Response(status=204)
|
|
||||||
else:
|
|
||||||
raise ValidationError(**PKS_ERROR)
|
|
||||||
|
|
||||||
@action(methods=['post'], detail=False, serializer_class=PkSerializer, permission_classes=[IsAdminUser])
|
|
||||||
def deletes_hard(self, request, *args, **kwargs):
|
|
||||||
"""批量物理删除
|
|
||||||
|
|
||||||
批量物理删除
|
|
||||||
"""
|
|
||||||
request_data = request.data
|
|
||||||
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)
|
|
||||||
except Exception:
|
|
||||||
self.get_queryset().filter(id__in=pks).delete()
|
|
||||||
return Response(status=204)
|
|
||||||
else:
|
|
||||||
raise ValidationError(**PKS_ERROR)
|
|
||||||
|
|
||||||
@swagger_auto_schema(request_body=ComplexSerializer, responses={200: {}})
|
@swagger_auto_schema(request_body=ComplexSerializer, responses={200: {}})
|
||||||
@action(methods=['post'], detail=False, perms_map={'post': '*'})
|
@action(methods=['post'], detail=False, perms_map={'post': '*'})
|
||||||
def cquery(self, request):
|
def cquery(self, request):
|
||||||
|
|
Loading…
Reference in New Issue