使用Django Rest框架序列化泛型关系,并提供写支持

使用Django Rest框架序列化泛型关系,并提供写支持,django,django-rest-framework,django-contenttypes,django-generic-relations,Django,Django Rest Framework,Django Contenttypes,Django Generic Relations,我有以下型号: class TaggedItem(models.Model): tag = models.SlugField() content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE) object_id = models.PositiveIntegerField() content_object = GenericForeignKey('content_type', 'obj

我有以下型号:

class TaggedItem(models.Model):
    tag = models.SlugField()
    content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
    object_id = models.PositiveIntegerField()
    content_object = GenericForeignKey('content_type', 'object_id')
我试图以一种可以通过API端点分配内容对象的方式序列化此模型

到目前为止,我已经做到了:

class TaggedItemSerializer(serializers.ModelSerializer):
    content_object = serializers.RelatedField(read_only=True)

    class Meta:
        model = TaggedItem
然而,这是只读的。如果删除只读参数,则必须为字段指定queryset。但是,对于这种泛型关系,我有许多不同的模型类型。如果我在序列化程序和模型中的其他地方指定所有可能的模型类型,那么我似乎是在复制代码

我还可以通过object_id和content_type字段设置content对象,但是当我这样做时,会出现一个错误

例如:

{
    ...
    object_id: 1,
    content_type: 'auth.User'
}
返回一个400响应,其中包含“详细信息”:“JSON解析错误-预期的对象或值”


如何通过DRF api使此内容对象可写?

覆盖
。到内部\u值
。验证
。创建如下方法:

from django.apps import apps

class TaggedItemSerializer(serializers.ModelSerializer):

    class Meta:
        model = TaggedItem
        read_only_fields = ('content_type', 'object_id', 'content_object')

    def to_internal_value(self, data):
        object_id = data.pop('object_id')
        content_type = data.pop('content_type')

        ret = super(ConfigCalcSerializer, self).to_internal_value(data)

        ret['object_id'] = object_id
        ret['content_type'] = content_type

        return ret

    def validate(self, data):
        object_id = data.pop('object_id')
        content_type = data.pop('content_type')

        Model = apps.get_model(content_type)

        try:
            content_object = Model.objects.get(id=object_id)
        except Model.DoesNotExist:
            raise serializers.ValidationError('Not found')
        else:
            data['content_object'] = content_object

        return data

    def create(self, validate_data):
        return TaggedItem.objects.create(**validate_data)