首页 文章

如何在DRF中序列化GenericForeignKey?

提问于
浏览
1

我有一个使用通用外键的模型,使用“content_type”字段存储内容类型,使用“object_id”存储对象ID . 需要使用CRUD API操作此模型,并且我正在使用DRF . 我有一个模型的序列化器,但我遇到了一些问题 . 如果我只是将content_type添加到这样的字段列表中

class MySerializer(ModelSerializer):
    class Meta:
        fields = ('name', 'state', 'content_type', 'object_id')

序列化程序将JSON表示设置为ContentType模型实例的ID . API的用户不知道这些ID,我不想用另一个API公开ContentType模型 . API用户确实知道他们想要链接的对象类型,因此他们可以发送内容类型名称 . 所以,我已经定义了这样的序列化器

class MySerializer(ModelSerializer):
    content_type = serializers.CharField(source="content_type.name")
    class Meta:
        fields = ('name', 'state', 'content_type', 'object_id')

序列化模型工作得很好 . 如果我使用通用关系链接User实例,我会得到类似 {'name': 'test', 'state': 'NY', 'content_type': 'user', 'object_id': 123} 的内容 . 但是当我使用JSON结构提交PUT或POST请求时,DRF会将其转换为类似 {'name': 'test', 'state': 'NY', 'content_type': {'name': {'name': 'user'}}, 'object_id': 123} 的内容 . 我可以写点类似的东西

def create(self, validated_data):
        ct_model = validated_data['content_type']['name']['name']
        validated_data['content_type'] = ContentType.objects.get(model=ct_model)
        return MyModel.objects.create(**validated_data)

但这似乎是武断的 . 处理这种情况的正确方法是什么?

Update #1: 目前,我已通过使用此代码覆盖to_internal_value()解决了该问题

def to_internal_value(self, data):
    content_type = data.get('content_type', None)
    validated_data = super().to_internal_value(data)
    try:
        validated_data['content_type'] = ContentType.objects.get(model=content_type)
    except ContentType.DoesNotExist:
        raise serializers.ValidationError("invalid content type %s" % content_type)
    return validated_data

对于显示相关对象而言,这似乎是一种丑陋的黑客行为 .

1 回答

  • 0

    您可能必须自定义,提供自己的字段类,使用 to_representationto_internal_value 方法来序列化此类关系 . 它并不复杂,试一试 .

    请考虑使用uri符号 /api/resource/object_id 作为序列化格式 .

    将内容类型转换为资源uris并返回可能有点挑战(如果您有多种可能的类型)但我确信必须有一些简单的方法来实现它 .

相关问题