feat: 增加幂等装饰器并用在create方法上

This commit is contained in:
caoqianming 2023-03-17 16:24:09 +08:00
parent 6a328a25c8
commit bb5e9925ea
3 changed files with 34 additions and 0 deletions

View File

@ -1,6 +1,7 @@
from rest_framework.views import APIView from rest_framework.views import APIView
from rest_framework.exceptions import ParseError
from rest_framework.permissions import IsAdminUser from rest_framework.permissions import IsAdminUser
from rest_framework.response import Response from rest_framework.response import Response
from rest_framework.serializers import Serializer from rest_framework.serializers import Serializer
@ -28,6 +29,8 @@ from apps.wf.models import State, Transition, Workflow
from django.db import transaction from django.db import transaction
from apps.utils.snowflake import idWorker from apps.utils.snowflake import idWorker
from django.core.cache import cache from django.core.cache import cache
import json
from apps.utils.decorators import auto_log, idempotent
# Create your views here. # Create your views here.
@ -185,12 +188,14 @@ class TestViewSet(CustomGenericViewSet):
'employee': '访客石非凡', 'event': '未带安全帽'}) 'employee': '访客石非凡', 'event': '未带安全帽'})
return Response() return Response()
@idempotent()
@action(methods=['post'], detail=False, serializer_class=Serializer) @action(methods=['post'], detail=False, serializer_class=Serializer)
def test_snap_only(self, request, pk=None): def test_snap_only(self, request, pk=None):
"""通道抓图 """通道抓图
通道抓图 通道抓图
""" """
return Response()
return Response(dhClient.snap(request.data['code'])) return Response(dhClient.snap(request.data['code']))
@action(methods=['post'], detail=False, serializer_class=Serializer) @action(methods=['post'], detail=False, serializer_class=Serializer)

View File

@ -2,6 +2,9 @@ import logging
from functools import wraps from functools import wraps
from apps.utils.tasks import send_mail_task from apps.utils.tasks import send_mail_task
import traceback import traceback
import json
from django.core.cache import cache
from rest_framework.exceptions import ParseError
myLogger = logging.getLogger('log') myLogger = logging.getLogger('log')
@ -21,3 +24,24 @@ def auto_log(name='', raise_exception=True, send_mail=False):
raise raise
return wrapper return wrapper
return decorate return decorate
def idempotent(seconds=4):
def decorate(func):
@wraps(func)
def wrapper(*args, **kwargs):
rdata = args[1].data
rdata['request_userid'] = getattr(args[1], 'user').id
print(getattr(args[1], 'user'), rdata)
hash_k = hash(json.dumps(rdata))
hash_v_e = cache.get(hash_k, None)
if hash_v_e is None:
cache.set(hash_k, 'o', seconds)
real_func = func(*args, **kwargs)
# real_func.render()
# cache.set(hash_k, real_func, seconds)
return real_func
elif hash_v_e == 'o': # 说明请求正在处理
raise ParseError(f'请求忽略,请{seconds}秒后重试')
return wrapper
return decorate

View File

@ -16,6 +16,7 @@ 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
class CustomGenericViewSet(MyLoggingMixin, GenericViewSet): class CustomGenericViewSet(MyLoggingMixin, GenericViewSet):
@ -145,6 +146,10 @@ 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) @action(methods=['post'], detail=False, serializer_class=PkSerializer)
def deletes(self, request, *args, **kwargs): def deletes(self, request, *args, **kwargs):
""" """