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

DRF POST接口无法保存Product:提示用户已存在错误

DRF添加产品接口提示“用户已存在”无法保存的解决方法

问题描述

使用Django Rest Framework开发添加产品的POST接口时,传入包含已有用户信息的JSON数据,serializer.is_valid()返回false,提示“用户已存在”,无法将Product保存到数据库。但通过Django管理后台可以正常为该用户创建产品。

相关代码如下:

views.py

@api_view(['POST'])
def addProduct(request):
    serializer = ProductSerializer(data = request.data)
    if serializer.is_valid():
        print("valid!!!")
        serializer.save()
        return Response(serializer.data, status=status.HTTP_201_CREATED)
    return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

serializers.py(原代码)

from rest_framework import serializers
from django.contrib.auth.models import User
from products.models import Product
from userProfile.serializers import UserSerializer

class ProductSerializer(serializers.ModelSerializer):
    user = UserSerializer()
    class Meta:
        model = Product
        fields = "__all__"

Product模型

class Product(models.Model):
    uuid = models.CharField(max_length=100)
    product_name = models.CharField(max_length=50)
    model = models.CharField(max_length=30)
    date_of_purchase = models.DateField()
    description = models.TextField()
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    defects = models.CharField(max_length=500)
    price = models.IntegerField(default=100)
    slug = models.SlugField(max_length=200)
    
    def save(self, *args, **kwargs):
        self.slug = slugify(self.uuid)
        super(Product, self).save(*args, **kwargs)

    def __str__(self):
        return f"{self.product_name}"

UserSerializer

from rest_framework import serializers
from django.contrib.auth.models import User

class UserSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = ['username','first_name', 'last_name','email','date_joined','is_staff','is_active']

传入的JSON数据

{
    "id": 4,
    "user": {
        "username": "Anirudh",
        "first_name": "",
        "last_name": "",
        "email": "email@email.com",
        "date_joined": "2023-06-15T15:15:57.138400Z",
        "is_staff": true,
        "is_active": true
    },
    "uuid": "qwerty",
    "product_name": "Phone",
    "model": "iPhone 12 mini 64GB",
    "date_of_purchase": "2021-08-15",
    "description": "Working condition, no dents. all buttons work. Upgrading to new phone so I am selling",
    "defects": "None",
    "price": 20000,
    "slug": "qwerty"
}

原因分析

原代码中ProductSerializer使用了嵌套的UserSerializer(),DRF默认会将嵌套序列化器的逻辑处理为创建新的关联对象。也就是说,当你传入完整的用户信息时,DRF尝试创建一个新的User实例,但该用户的username或email已经存在于数据库中,触发了User模型的唯一约束,导致is_valid()校验失败,提示“用户已存在”。

而Django管理后台是通过选择已有用户的主键来关联,并非创建新用户,所以不会出现这个问题。

解决方案

方法一:使用主键关联(推荐)

直接通过用户ID关联已有用户,不需要传入完整用户信息,修改ProductSerializer:

from rest_framework import serializers
from django.contrib.auth.models import User
from products.models import Product

class ProductSerializer(serializers.ModelSerializer):
    # 改为PrimaryKeyRelatedField,指定查询集
    user = serializers.PrimaryKeyRelatedField(queryset=User.objects.all())
    class Meta:
        model = Product
        fields = "__all__"

对应的JSON数据可以简化为:

{
    "id": 4,
    "user": 4,  // 替换为实际存在的用户ID
    "uuid": "qwerty",
    "product_name": "Phone",
    "model": "iPhone 12 mini 64GB",
    "date_of_purchase": "2021-08-15",
    "description": "Working condition, no dents. all buttons work. Upgrading to new phone so I am selling",
    "defects": "None",
    "price": 20000,
    "slug": "qwerty"
}

方法二:自定义create方法关联已有用户

如果业务需求必须传入完整用户信息,可以重写序列化器的create方法,手动获取已有用户并关联:

from rest_framework import serializers
from django.contrib.auth.models import User
from products.models import Product
from userProfile.serializers import UserSerializer

class ProductSerializer(serializers.ModelSerializer):
    user = UserSerializer()
    class Meta:
        model = Product
        fields = "__all__"

    def create(self, validated_data):
        # 取出用户数据
        user_data = validated_data.pop('user')
        # 通过username获取已有用户(可根据实际情况用email等唯一字段)
        user = User.objects.get(username=user_data['username'])
        # 创建Product并关联用户
        product = Product.objects.create(user=user, **validated_data)
        return product

注意:如果使用这种方法,需要确保传入的用户信息能唯一匹配到数据库中的用户,否则会抛出User.DoesNotExist异常,可根据需求添加异常处理逻辑。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 05:02:04