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 }
总结常见踩坑点
- 视图用错类,没选Update系列视图
- URL没带主键参数,视图找不到要更新的记录
- 用POST请求却没手动处理更新逻辑
- Serializer漏了主键字段,或者自定义update逻辑出错
对照这几点检查你的代码,应该就能搞定啦!
内容的提问来源于stack exchange,提问作者Lhou A
相关产品推荐
相关产品推荐

