【问题标题】:How to serialize GenericForeignKey in DRF?如何在 DRF 中序列化 GenericForeignKey?
【发布时间】:2016-12-24 13:26:41
【问题描述】:

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

MySerializer 类(ModelSerializer): 元类: 字段 = ('name', 'state', 'content_type', 'object_id')

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

MySerializer 类(ModelSerializer): content_type = serializers.CharField(source="content_type.name") 元类: 字段 = ('name', 'state', 'content_type', 'object_id')

序列化模型效果很好。如果我使用通用关系链接一个用户实例,我会得到类似{'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} 的内容。我可以写类似的东西

定义创建(自我,验证数据): ct_model = 验证数据['content_type']['name']['name'] 验证数据['content_type'] = ContentType.objects.get(model=ct_model) 返回 MyModel.objects.create(**validated_data)

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

更新 #1: 目前,我已经通过使用此代码覆盖 to_internal_value() 解决了这个问题

def to_internal_value(自我,数据): content_type = data.get('content_type', 无) 验证数据 = super().to_internal_value(数据) 尝试: 验证数据['content_type'] = ContentType.objects.get(model=content_type) 除了 ContentType.DoesNotExist: raise serializers.ValidationError("invalid content type %s" % content_type) 返回已验证数据

显示相关对象似乎是一种丑陋的黑客行为。

【问题讨论】:

  • 您尝试过文档django-rest-framework.org/api-guide/relations/… 中的解决方案吗?
  • 解决方案似乎是定义一个自定义的相关字段类。我会调查一下,但这似乎很复杂。
  • 如果您已经回答了自己的问题,请将其发布为答案而不是更新。
  • 这不是我要找的答案。我想出了一个丑陋的技巧,似乎可以解决我遇到的直接问题。它很脆弱,效率不高。我仍在寻找更好的方法。

标签: django django-rest-framework


【解决方案1】:

您可能必须进行自定义,为您自己的字段类提供to_representationto_internal_value 方法来序列化此类关系。没那么复杂,试试看吧。

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

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

【讨论】:

  • 如果我使用 URI 作为内容类型,我将不得不 1. 通过 API 公开内容类型(并处理大量的权限和过滤问题,因为 django 为系统) 2. 强制API用户多次请求获取一条数据。
  • 我不认为你的 1. 是真的,我不知道你怎么能避免权限和过滤但是如果你 2. 想要你的 api 嵌套和慢,你仍然很可能有自定义上述序列化方法。
  • 如果我将uris用于嵌套资源,应该可以使用uri来获取资源。在这种情况下,您建议将 uris 用于内容类型,这意味着我需要一个 API 来访问内容类型。这导致不得不以一些不明显的方式限制对它的访问,因为 django 为绝对所有内容创建内容类型,我不想将应用程序的内部结构暴露给 API 用户。至于第二部分,我没有让我的 API 嵌套。但即使我这样做了,我也不确定你是否有资格评判它的表现。
猜你喜欢
  • 2016-04-23
  • 1970-01-01
  • 1970-01-01
  • 2018-04-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-09-21
相关资源
最近更新 更多