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

Django数据库更新异常:执行代码新增而非更新数据求助

哥们,我太懂你这种明明想更新现有记录,结果代码反手给你新增一条的崩溃感!咱一步步拆解问题,搞定reservedplaces字段的更新需求~

先从视图(View)找问题:别用错视图类!

DRF里如果选不对视图类,大概率会触发「新增」而非「更新」逻辑:

  • 如果你用了CreateAPIView或者只重写了post方法的GenericAPIView,默认就会走创建流程
  • 正确姿势是用专门的更新视图:
    • 单条记录更新用UpdateAPIView(仅支持更新)或者RetrieveUpdateAPIView(同时支持查询+更新)
    • 要是需要完整的增删改查,直接用ModelViewSet更省心

举个正确的视图示例:

# 方式1:仅支持更新的视图
from rest_framework.generics import UpdateAPIView
from .models import YourModel
from .serializers import YourSerializer

class ReservedUpdateView(UpdateAPIView):
    queryset = YourModel.objects.all()
    serializer_class = YourSerializer

# 方式2:支持全量操作的视图集
from rest_framework.viewsets import ModelViewSet

class YourModelViewSet(ModelViewSet):
    queryset = YourModel.objects.all()
    serializer_class = YourSerializer
再检查URL配置:必须传主键!

视图要知道「更新哪条记录」,就得从URL里拿到主键参数。如果URL没加<int:pk>,视图找不到目标记录,就会默认创建新数据。

正确的URL配置示例:

from django.urls import path
from .views import ReservedUpdateView, YourModelViewSet
from rest_framework.routers import DefaultRouter

# 对应UpdateAPIView的URL
urlpatterns = [
    path('your-model/update/<int:pk>/', ReservedUpdateView.as_view(), name='update-reserved'),
]

# 对应ModelViewSet的URL(自动生成包含update的路由)
router = DefaultRouter()
router.register('your-model', YourModelViewSet)
urlpatterns += router.urls
然后看Serializer:别搞砸update逻辑!

ModelSerializer默认已经实现了正确的update方法,但如果你自定义了create或者update方法,就可能出问题:

  • 要确保Serializer里包含主键字段(比如id),让DRF能定位到目标记录
  • 自定义update时,别漏了保存实例的逻辑

示例Serializer:

from rest_framework import serializers
from .models import YourModel

class YourSerializer(serializers.ModelSerializer):
    class Meta:
        model = YourModel
        fields = ['id', 'reservedplaces', ...]  # 明确包含主键和要更新的字段

    # 要是自定义update,逻辑得写对
    def update(self, instance, validated_data):
        # 只更新reservedplaces,其他字段保留原值
        instance.reservedplaces = validated_data.get('reservedplaces', instance.reservedplaces)
        instance.save()
        return instance
最后看请求:别用错请求方法!

DRF的默认规则里:

  • PUT用于全量更新单条记录
  • PATCH用于局部更新单条记录
  • POST默认是创建新记录

如果你非要用POST做更新,得在视图里重写post方法,手动指定要更新的实例:

class ReservedUpdateView(GenericAPIView):
    queryset = YourModel.objects.all()
    serializer_class = YourSerializer

    def post(self, request, pk=None):
        # 通过pk拿到要更新的实例
        instance = self.get_object()
        # partial=True允许只传需要更新的字段
        serializer = self.get_serializer(instance, data=request.data, partial=True)
        serializer.is_valid(raise_exception=True)
        serializer.save()
        return Response(serializer.data)

另外请求要传对参数:URL里带上目标记录的pk,请求体只传要更新的字段就行,比如:

{
    "reservedplaces": 6
}
总结常见踩坑点
  1. 视图用错类,没选Update系列视图
  2. URL没带主键参数,视图找不到要更新的记录
  3. 用POST请求却没手动处理更新逻辑
  4. Serializer漏了主键字段,或者自定义update逻辑出错

对照这几点检查你的代码,应该就能搞定啦!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 04:12:00