当前位置: 首页 > 知识库问答 >
问题:

如何在DRF中序列化GenericForeignKey?

梁兴文
2023-03-14

我有一个模型,它使用一个通用外键,使用“content\u type”字段来存储内容类型,“object\u id”来存储对象id。这个模型需要使用CRUD API进行操作,我使用的是DRF。我有一个模型的序列化程序,但我遇到了一点问题。如果我只是将content\u 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')

序列化模型效果很好。如果我使用泛型关系链接一个用户实例,我会得到类似{'name':'test','state':'NY','content\u type':'User','object\u id':123}。但当我提交一个带有JSON结构的PUT或POST请求时,DRF会将其转换为类似于{'name':'test','state':'NY','content\u type':{'name':'user'}},'object\u 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)

但它似乎武断而脆弱。处理这种情况的正确方法是什么?

更新#1:目前,我已经解决了这个问题,使用以下代码重写为_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个答案

闻人景澄
2023-03-14

您可能需要进行自定义,为自己的字段类提供to_表示法to_内部值方法来序列化此类关系。没那么复杂,试试看。

考虑使用uri符号/api/Resources/object_id作为序列化格式。

将内容类型转换为资源URI并将其转换为资源URI可能有点困难(如果您有多种可能的类型),但我相信一定有一些简单的方法可以做到这一点。

 类似资料:
  • 一套 RESTful Web API,最基本的要求就是能为调用该 API 的客户端提供符合要求的数据类型,而能否提供符合要求的数据类型,序列化器是关键。上一节中,我们通过短短 6 行代码,构建了一个序列化器,那么序列化器是如何工作的呢?这一节,我们就带领大家手动构建一个序列化器,并深入介绍序列化器的详细使用方法。 1. 构建序列化器 我们在已有的一个数据库模型类 StudentsInfo: # m

  • 问题内容: 如何序列化未实现Serializable的对象?我不能将其标记为Serializable,因为该类来自第3方库。 问题答案: 您不能序列化未实现的类,但可以将其包装在可以实现的类中。为此,您应该在包装器类上实现和,以便可以以自定义方式序列化其对象。 首先,使您的非序列化字段。 在中,首先调用流以存储所有非瞬态字段,然后调用其他方法来序列化不可序列化对象的各个属性。 在中,首先调用流以读

  • 问题内容: 我的直觉告诉我,必须以某种方式将其转换为字符串或byte [](在Go中甚至可能是相同的东西?),然后将其保存到磁盘。 我找到了这个包(http://golang.org/pkg/encoding/gob/),但似乎仅用于结构? 问题答案: 序列化数据有多种方法,Go为此提供了许多软件包。某些常见编码方式的软件包: 处理地图很好。以下示例显示了地图的编码/解码: 操场

  • 我有一个kdtree,其节点由以下字段组成:公共静态类节点实现可序列化{ 其中DataPoint定义: 公共静态类DataPoint实现可序列化{公共可比X;公共可比Y;公共可比Z; 我想序列化树,存储在文件中并在回答范围查询时反序列化。我对这个概念od序列化的理解并不好。从我收集的任何内容中,我编写了以下函数,但不起作用。有人能帮忙吗?

  • 问题内容: 我想深入克隆一个列表。为此,我们有一种方法 所以现在要克隆我的列表,我应该先将其转换为可序列化的。是否可以将列表转换为可序列化列表? 问题答案: 已实施的所有标准实施。 因此,即使它本身不是的子类型,也可以安全地将列表强制转换为,只要您知道它是诸如或的标准实现之一。 如果不确定,请先复制列表(使用),然后知道它是可序列化的。

  • 我使用下面的方法(来自spark-java framework的方法)从DB返回的数据如下: 从DB返回的数据: ClasStypeAdapterFactory: 类类型适配器: 这里我使用的是,它从spark-java ResponseTransformer接口实现了