Django Rest Framework POST未保存到数据库产品错误:用户已存在

vawmfj5a  于 2023-06-25  发布在  Go
关注(0)|答案(1)|浏览(102)
@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)

以上是我的www.example.com添加产品views.py for adding a product
下面是我的www.example.com 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用于ProductSerializer

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']

我的输入:

{
    "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"
}

我收到一个错误,说明用户已经存在,这个用户名我可以从django管理面板创建来自同一用户的产品,但不能使用DRF创建。当I POST数据时,if serializer.is_valid():为假

zte4gxcn

zte4gxcn1#

默认情况下,.create()方法不支持可写嵌套字段。所以你需要自己写。另外,有效负载中的id也是不相关的,因为您正在创建新对象。
一个可能的选择是在view中从request.data中删除user,并将其作为额外的上下文传递给ProductSerializer。在这里,我们覆盖.create,并使用此数据来检查User是否存在,如果不存在,我们将创建一个。
views.py

@api_view(['POST'])
def addProduct(request):
    user = request.data.pop('user')
    serializer = ProductSerializer(data=request.data, context={'user': user})
    
    if serializer.is_valid(raise_exception=True):
        print("valid!!!")
        serializer.save()
        return Response(serializer.data, status=status.HTTP_201_CREATED)

serializers.py

class ProductSerializer(serializers.ModelSerializer):
    class Meta:
        model = Product
        fields = "__all__"
        extra_kwargs = {"user": {"required": False}}

    def create(self, validated_data):
        user_data = self.context.get("user", None)
        try:
            user_instance = User.objects.get(username=user_data["username"])
            validated_data["user"] = user_instance
        except User.DoesNotExist:
            serializer = UserSerializer(data=user_data)
            if serializer.is_valid(raise_exception=True):
                user_instance = serializer.save()
                validated_data["user"] = user_instance

        return super().create(validated_data)

    def to_representation(self, instance):
        representation = super().to_representation(instance)

        user_id = representation.pop("user")
        user_instance = User.objects.get(pk=user_id)
        serializer = UserSerializer(user_instance)
        representation["user"] = serializer.data
        return representation

覆盖.to_representation是可选的,我这样做是为了获得与有效负载相同格式的响应,否则它只返回用户id

相关问题