如何在Django API中按价格条件延迟重发创建请求?
解决方案
首先不建议在同步API视图中直接用time.sleep阻塞线程,这会拖慢服务的并发处理能力。如果一定要实现需求,可以通过递归调用自身+重试次数限制的方式完成,同时避免无限循环:
修改后的代码
from rest_framework import status from rest_framework.response import Response import time class BuyProductViewset(viewsets.GenericViewSet, mixins.CreateModelMixin): serializer_class = UserproductSerializer queryset = Userproducts.objects.all() # 设定最大重试次数,防止无限递归耗尽资源 MAX_RETRIES = 3 def data_serialize(self, user_id, product_ID): data = {"user": user_id, "product": product_ID} serializer = self.get_serializer(data=data) serializer.is_valid(raise_exception=True) self.perform_create(serializer) headers = self.get_success_headers(serializer.data) return serializer, headers def create(self, request, *args, **kwargs): # 获取当前重试次数,默认0 retry_count = kwargs.get('retry_count', 0) user_id = request.data["user_id"] product_id = request.data["product_id"] total = request.data["total"] upper_bound = request.data["upper_bound"] lower_bound = request.data["lower_bound"] # 模型类名修正为大写(Django规范),用last()替代reverse[:1].get()更简洁 product = ( Product.objects.filter(product_id=product_id) .order_by("timestamp") .last() ) if not product: return Response({"error": "商品不存在"}, status=status.HTTP_404_NOT_FOUND) product_ID = product.id product_price = product.price product_availability = product.availability product_name = product.name if product_price >= int(lower_bound) and product_price <= int(upper_bound): serializer, headers = self.data_serialize(user_id, product_ID) # 原代码逻辑错误:创建新商品而非更新库存,这里改为update修正 Product.objects.filter(id=product_ID).update( availability=product_availability - int(total) ) return Response( serializer.data, status=status.HTTP_201_CREATED, headers=headers ) else: # 超过重试上限则返回失败 if retry_count >= self.MAX_RETRIES: return Response( {"error": f"经过{self.MAX_RETRIES}次重试后,商品价格仍不在指定区间"}, status=status.HTTP_400_BAD_REQUEST ) # 延迟5秒后递归调用自身,重试次数+1 time.sleep(5) return self.create(request, *args, **kwargs, retry_count=retry_count+1)
关键说明
- 重试次数控制:添加
MAX_RETRIES常量,避免因价格持续不符合条件导致无限递归,保护服务器资源。 - 递归实现重发:在else分支中,延迟后调用自身的
create方法,复用原请求数据并递增重试次数,完成重复请求逻辑。 - 代码修正与优化:
- 遵循Django模型类名大写规范,修正原代码中的
product为Product。 - 替换
reverse()[:1].get()为last(),简化最新商品查询逻辑。 - 修正原代码中错误的库存更新逻辑:原代码会创建新商品实例,改为用
update修改现有商品的库存数量。 - 添加商品不存在的判断,避免
get()抛出未捕获异常。
- 遵循Django模型类名大写规范,修正原代码中的
更优方案(推荐)
同步视图阻塞线程会严重影响服务并发能力,建议改用异步任务队列(如Celery)实现延迟重试:
- 当价格不符合条件时,将请求数据存入任务队列,设置5秒延迟后执行。
- 任务执行时重新检查价格,符合条件则创建
Userproducts并更新库存,否则可继续重试或通知用户。
内容的提问来源于stack exchange,提问作者Menna Magdy
相关产品推荐
相关产品推荐

