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

求助:如何在Django REST Framework中实现POST请求的增改逻辑

Django REST Framework 批量创建/更新(Upsert)实现方案

需求说明

通过POST请求实现批量数据的创建(当用户不存在时)或更新(当用户存在时),具体逻辑:

  • 若用户(按user字段匹配)已存在:
    • 若full_name与请求数据一致,仅更新logon_data
    • 若full_name不一致,同时更新full_name和logon_data
  • 若用户不存在,创建新用户记录

POST请求JSON示例:

[
    {
        "user": "testuser1",
        "full_name": "test user1",
        "logon_data": "2022-10-19 09:37:26"
    },
    {
        "user": "testuser2",
        "full_name": "test user2",
        "logon_data": "2022-10-20 07:02:06"
    }
]

现有代码

models.py

class User1(models.Model):
    user = models.CharField(max_length=10)
    full_name = models.CharField(max_length=20)
    logon_data = models.DateTimeField(blank=True, null=True)

serializers.py

class UserSerializer(serializers.ModelSerializer):
    class Meta:
        model = User1
        fields = '__all__'

views.py

from .models import User1
from .serializers import UserSerializer
from rest_framework.response import Response
from rest_framework.decorators import api_view

@api_view(['GET', 'POST'])
def UserView(request):
    if request.method == 'GET':
        users = User1.objects.all()
        serializer = UserSerializer(users, many=True)
        return Response(serializer.data)
    elif request.method == 'POST':
        users = User1.objects.all()
        serializer = UserSerializer(data=request.data, many=True)

        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=201)
        return Response(serializer.errors, status=400)

urls.py

from django.urls import path
from . import views

urlpatterns = [
    path('users/', views.UserView),
]

解决方案

修改views.py中的POST处理逻辑,逐个处理每条请求数据,实现Upsert逻辑:

修改后的views.py

from .models import User1
from .serializers import UserSerializer
from rest_framework.response import Response
from rest_framework.decorators import api_view
from rest_framework import status

@api_view(['GET', 'POST'])
def UserView(request):
    if request.method == 'GET':
        users = User1.objects.all()
        serializer = UserSerializer(users, many=True)
        return Response(serializer.data)
    elif request.method == 'POST':
        response_data = []
        errors = []
        for item in request.data:
            # 按user字段查找现有记录
            try:
                user_obj = User1.objects.get(user=item['user'])
                # 存在则更新
                update_fields = []
                if user_obj.full_name != item['full_name']:
                    user_obj.full_name = item['full_name']
                    update_fields.append('full_name')
                # 无论full_name是否变化,都更新logon_data
                user_obj.logon_data = item['logon_data']
                update_fields.append('logon_data')
                # 只更新修改过的字段,减少数据库开销
                user_obj.save(update_fields=update_fields)
                # 序列化更新后的对象
                serializer = UserSerializer(user_obj)
                response_data.append(serializer.data)
            except User1.DoesNotExist:
                # 不存在则创建
                serializer = UserSerializer(data=item)
                if serializer.is_valid():
                    serializer.save()
                    response_data.append(serializer.data)
                else:
                    errors.append({'user': item['user'], 'errors': serializer.errors})
        
        if errors:
            return Response({'success': response_data, 'errors': errors}, status=status.HTTP_400_BAD_REQUEST)
        return Response(response_data, status=status.HTTP_200_OK if response_data else status.HTTP_400_BAD_REQUEST)

补充优化

为避免同一user字段出现多条重复记录,建议在models.py中给user字段添加唯一约束:

class User1(models.Model):
    user = models.CharField(max_length=10, unique=True)  # 添加unique=True
    full_name = models.CharField(max_length=20)
    logon_data = models.DateTimeField(blank=True, null=True)

添加后执行数据库迁移命令:

python manage.py makemigrations
python manage.py migrate

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 01:31:21