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

使用Django REST Framework创建供应商函数时遇问题求助

问题描述

我是一名Flask开发者,当前正在使用Django开发项目。采用Firebase进行认证,使用Django REST Framework整合时遇到问题:尝试为用户创建供应商时未成功,返回结果不符合预期。

请求详情

  • 请求地址:http://localhost:8000/pm/createsupplier/3/
  • 请求体:
{
    "supplier": {"name": "Donald Duck", "phone": 111, "email": "donald@yahoo.com"}
}
  • 响应结果:
{
    "email": "kbess86@gmail.com"
}

相关代码

models.py

class UserProfile(models.Model):
    user = models.OneToOneField(User,on_delete=models.CASCADE)
    bio = models.CharField(max_length=200)
    email = models.CharField(max_length=200)

class Supplier(models.Model):
    user = models.ForeignKey(UserProfile, on_delete=models.CASCADE)
    name = models.CharField(max_length=200)
    phone = models.IntegerField()
    email = models.EmailField()

views.py

class createsuppliers(viewsets.ModelViewSet):
    queryset = UserProfile.objects.all()
    serializer_class = CreateSupplierSerializer
    lookup_field = 'user'

serializers.py

class CreateSupplierSerializer(serializers.ModelSerializer):
    name = serializers.CharField(required=False, allow_blank=True, max_length=100)
    email = serializers.CharField(required=False, allow_blank=True, max_length=100)
    phone = serializers.IntegerField(required=False)

    def create(self, instance, validated_data):
        supplier_data = validated_data.pop('supplier')
        supplier = Supplier.objects.create(user=instance, **supplier_data)

        return supplier
    class Meta:
        model=Supplier
        fields=['name','email','phone']

问题分析与修复

1. 视图类逻辑错误

当前createsuppliers继承ModelViewSet但用法错误:

  • lookup_field设为user,但UserProfile的主键是id,URL中的3是UserProfile的id,导致视图无法正确定位实例。
  • ModelViewSet的默认create方法用于创建新的UserProfile,但需求是给已存在的UserProfile创建关联Supplier,应该改用自定义动作。

修改views.py:

from rest_framework import viewsets, status
from rest_framework.response import Response

class createsuppliers(viewsets.ViewSet):
    queryset = UserProfile.objects.all()

    def create_supplier(self, request, pk=None):
        # 获取对应的UserProfile实例
        user_profile = self.get_object()
        # 传入请求数据和上下文
        serializer = CreateSupplierSerializer(data=request.data, context={'user_profile': user_profile})
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

同时在urls.py中配置路由:

path('pm/createsupplier/<int:pk>/', createsuppliers.as_view({'post': 'create_supplier'})),

2. 序列化器核心错误

  • create方法签名错误:ModelSerializer的create方法应为def create(self, validated_data),你写成了def create(self, instance, validated_data)(这是update方法的签名)。
  • 未正确处理嵌套的supplier字段,需要定义嵌套序列化器来接收请求体中的结构。
  • 序列化器字段与模型不匹配:Supplier的email是EmailField,序列化器用了CharField;name的max_length模型是200,序列化器设为100,且不必要地设置了required=False。

修改serializers.py(支持嵌套请求体):

class SupplierSerializer(serializers.ModelSerializer):
    class Meta:
        model = Supplier
        fields = ['name', 'email', 'phone']
        extra_kwargs = {
            'name': {'max_length': 200, 'required': True},
            'email': {'required': True},
            'phone': {'required': True}
        }

class CreateSupplierSerializer(serializers.Serializer):
    supplier = SupplierSerializer()

    def create(self, validated_data):
        supplier_data = validated_data.pop('supplier')
        # 从上下文获取UserProfile实例
        user_profile = self.context['user_profile']
        return Supplier.objects.create(user=user_profile, **supplier_data)

如果不需要嵌套结构,可简化序列化器,请求体直接传供应商字段:

class CreateSupplierSerializer(serializers.ModelSerializer):
    class Meta:
        model = Supplier
        fields = ['name', 'email', 'phone']
        extra_kwargs = {
            'name': {'max_length': 200, 'required': True},
            'email': {'required': True},
            'phone': {'required': True}
        }

    def create(self, validated_data):
        user_profile = self.context['user_profile']
        return Supplier.objects.create(user=user_profile, **validated_data)

此时请求体改为:

{"name": "Donald Duck", "phone": 111, "email": "donald@yahoo.com"}

3. 响应异常原因

之前返回UserProfile的email,是因为视图的queryset是UserProfile,ModelViewSet默认返回的是UserProfile实例数据,而非创建的Supplier数据。修改后的视图会返回正确的供应商信息。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 23:50:32