求助:如何在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
相关产品推荐
相关产品推荐

