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
相关产品推荐
相关产品推荐

