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

Django DRF创建含关联标签Item时的重复标签及序列化问题

DRF嵌套序列化器实现Item标签关联的问题

我需要实现一个功能:创建新Item时,若传入的标签不存在则自动创建,已存在则直接关联到Item上。为此编写了如下序列化器及create方法:

class TagSerializer(serializers.ModelSerializer):

    class Meta:
        model = models.Tag
        fields = ("id", "name", "style")

class ItemSerializer(serializers.ModelSerializer):

    tags = TagSerializer(many=True, required=False)

    class Meta:
        model = models.Item
        fields = "__all__"

    def create(self, validated_data):
        print(validated_data)
        tags = validated_data.pop("tags", [])
        item = models.Item.objects.create(**validated_data)
        for tag in tags:
            current_tag, _ = models.Tag.objects.get_or_create(**tag)
            item.tags.add(current_tag)
        return item

但当POST包含已存在标签的Item数据时:

{
    "tags": [{"name": "My Tag"}],
    "name": "My Item"
 }

收到DRF 400响应:

{
  "tags": [
    {
      "name": [
        "tag with this name already exists."
      ]
    }
  ]
}

看起来自定义的create方法被跳过,DRF仍会尝试创建标签,触发了Tag模型的唯一约束。


第一次修改后的异常

尝试修改TagSerializer为自定义Serializer并实现create方法,代码如下:

class TagSerializer(serializers.Serializer):

    id = serializers.UUIDField(read_only=True)
    name = serializers.CharField(required=True)
    style = serializers.JSONField(read_only=True)

    def create(self, validated_data):
        print(validated_data)
        name = validated_data.pop("name")
        tag, _ = models.Tag.objects.get_or_create(
            name=name, defaults=validated_data
        )
        return tag

class ItemSerializer(serializers.ModelSerializer):

    tags = TagSerializer(many=True, required=False)

    class Meta:
        model = models.Item
        fields = "__all__"

通过Swagger测试时触发500错误:

AssertionError: The `.create()` method does not support writable nested fields by default.
Write an explicit `.create()` method for serializer `core.serializers.ItemSerializer`, or set `read_only=True` on nested serializer fields.
[18/May/2025 09:04:01] "POST /api/core/item/ HTTP/1.1" 500 7765

单元测试中的标签丢失问题

使用APITestCase编写测试时,返回的Item未关联标签:

class TestAPIMissingTags(APITestCase):

    fixtures = [
        "core/fixtures/users.yaml"
    ]

    payload = {
        "name": "test",
        "tags": [{"name": "test"}, {"name": "critical"}],
    }

    def setUp(self):
        self.user = models.User.objects.get(username="jlandercy")
        self.client = APIClient()
        self.client.force_authenticate(user=self.user)

    def test_complete_payload_is_sent(self):
        response = self.client.post("/api/core/item/", data=self.payload)

接口返回201成功,但返回的Item中标签为空:

<Response status_code=201, "application/json">
{'id': 'f4f7a670-06d6-4bad-9979-3d0bd5bedd0c', 'tags': [], 'name': 'test'}

标签数据似乎被丢弃未处理,Swagger测试与单元测试表现不一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 02:26:19