You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

DRF使用UpdateModelMixin更新数据遇递归错误,求正确实现方式

解决UpdateModelMixin使用时的递归错误与正确数据更新方式

首先,你遇到的「maximum recursion depth exceeded」错误原因非常明确——你的put方法里写了return self.put(self,request,*kwargs,**kwargs),这相当于无限递归调用自己,Python的递归深度有限,自然会触发这个错误。

接下来给你梳理正确的实现方式,结合你要做的「仅允许用户更新自己的产品」这个需求,我们一步步调整代码:

核心修复与优化点

1. 修复递归调用问题

因为你继承了UpdateModelMixin,这个Mixin已经帮你实现了数据更新的核心逻辑(包括序列化验证、保存数据等),你只需要在put方法里调用它提供的update()方法即可,而不是自己调用put。

2. 统一实例获取逻辑

你原来的get方法里写了获取用户自有产品的逻辑,为了避免代码重复,同时让UpdateModelMixin能正确找到要更新的实例,我们需要重写get_object方法——这是DRF视图中用来获取单个实例的标准方法,Mixin的update方法也会依赖它来获取要修改的对象。

3. 规范错误响应

把原来返回400的逻辑换成抛出Http404异常,DRF会自动将其转换为404响应,这更符合REST规范(404表示资源不存在,400用于请求参数错误的场景)。

修改后的完整代码

from rest_framework.views import APIView
from rest_framework import mixins, status
from rest_framework.response import Response
from rest_framework.exceptions import Http404
from .models import Product
from .serializers import ProductSerializer

class ProductOwnserSingleViewAPIView(APIView, mixins.UpdateModelMixin):
    queryset = Product.objects.all()
    serializer_class = ProductSerializer

    def get_object(self):
        # 兼容URL路径传参和GET参数传ID的情况
        product_id = self.kwargs.get('id') or self.request.GET.get('id')
        if not product_id:
            raise Http404
        
        try:
            return Product.objects.get(
                author_id=self.request.user.id,
                product_id=product_id
            )
        except Product.DoesNotExist:
            raise Http404

    def put(self, request, *args, **kwargs):
        # 调用Mixin的update方法处理更新逻辑
        return self.update(request, *args, **kwargs)

    def get(self, request, *args, **kwargs):
        product = self.get_object()
        serializer = ProductSerializer(instance=product, context={"request": request})
        return Response(serializer.data)

额外说明

  • 如果是RESTful风格的API,更推荐把产品ID放在URL路径中(比如/api/products/123/),这时候你需要在URL配置中添加对应的参数,比如:
    # urls.py
    from django.urls import path
    from .views import ProductOwnserSingleViewAPIView
    
    urlpatterns = [
        path('api/products/<int:id>/', ProductOwnserSingleViewAPIView.as_view()),
    ]
    
  • 当你发送PUT请求时,只需要在请求体中携带需要更新的字段数据即可(ID已经通过URL或GET参数传递,不需要在请求体里重复携带,当然如果携带了也没关系,序列化器会忽略只读字段)。

内容的提问来源于stack exchange,提问作者devmrh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 04:09:15