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

DRF中仅更新模型两个字段时其他字段为空的问题

问题原因与解决方案

核心问题

你创建了一个新的Card实例requestd2 = card.models.Card(card_number=requestd),这个实例只有card_number字段有值,其余字段都是默认空值。当你用这个新实例执行partial=True的更新时,DRF会把这个新实例的空字段也保存到数据库,覆盖原有数据,导致其他字段变空。

正确的做法是从数据库获取已存在的Card实例,而非新建实例。

修正后的代码

from rest_framework.decorators import api_view
from rest_framework import status
from rest_framework.response import Response
from card.models import Card
from .serializers import CardModelSerializer

@api_view(['GET', 'PUT', 'DELETE'])
def snippet_detail(request, format=None):
    try:
        # 从请求数据中获取卡号(用request.data兼容PUT/POST请求)
        card_number = request.data.get('card_number')
        if not card_number:
            return Response('卡号不能为空', status=status.HTTP_400_BAD_REQUEST)
        
        # 从数据库获取已存在的Card实例
        card_instance = Card.objects.get(card_number=card_number)
        current_credit = card_instance.initial_credit
        request_credit = int(request.data.get('initial_credit', 0))

    except Card.DoesNotExist:
        return Response('卡号不存在', status=status.HTTP_404_NOT_FOUND)
    except ValueError:
        return Response('输入的金额格式错误', status=status.HTTP_400_BAD_REQUEST)

    if request.method == 'PUT':
        # 使用数据库中已存在的实例执行部分更新
        serializer = CardModelSerializer(card_instance, data=request.data, partial=True)
        if serializer.is_valid():
            comment = 'اعتبار کافی نمی باشد .'
            comment2 = 'مقدار وارد شده صحیح نمی باشد'
            
            if request_credit <= 0:
                return Response(comment2, status=status.HTTP_400_BAD_REQUEST)
            
            new_credit = current_credit - request_credit
            if new_credit >= 0:
                # 更新余额字段
                serializer.validated_data['initial_credit'] = new_credit
                serializer.save()
                return Response(serializer.data, status=status.HTTP_200_OK)
            else:
                return Response(comment, status=status.HTTP_451_UNAVAILABLE_FOR_LEGAL_REASONS)
        
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

关键优化点

  • 实例获取修正:用Card.objects.get(card_number=card_number)获取数据库中已有的记录,避免用新实例覆盖数据
  • 请求数据兼容:用request.data替代request.POST,适配DRF中PUT请求的数据处理逻辑
  • 异常处理完善:新增金额格式错误的捕获逻辑,避免非数字输入导致报错
  • 逻辑顺序调整:先校验金额合法性,再计算余额,代码逻辑更清晰
  • 字段更新方式:通过serializer.validated_data直接修改余额,确保更新后的数据正确

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 11:45:23