Django Rest框架 - 使用与__all__的反向关系

时间:2017-02-14 08:33:31

标签: python django serialization django-rest-framework

因此,我完全在Django Rest Framework的序列化器中使用了反向关系。我已成功实施了一个解决方案,可以让我在数据输出中看到我想要的内容。

然而,最终的实施让我有点不高兴。

基本上,我希望有一个API结果,它给了我相关模型的完整嵌套信息 - 所以模块包含其所有字段,然后是反向关系,SubModules及其所有字段。

因此,在我的示例中,我们依次为Modules提供了许多SubModules

子模块models.py具有如下关系:

module = models.ForeignKey(Module, related_name='sub_modules')

显然,模块models.py中没有定义直接的sub_modules属性。

因此,在模块serializer.py中,我想确保在sub_modules的API调用中返回完整的/api/modules个对象 - 而不是网址或ID。

所以,我最初的实现(不是我想要的)是这样的:

class ModuleSerializer(serializers.ModelSerializer):

    class Meta:
        model = Module
        fields = '__all__'
        depth = 1

然而,这会返回以下内容(注意,没有sub_modules):

{
    "id": 1,
    "created_at": "2017-02-13T11:19:28.665000Z",
    "updated_at": "2017-02-13T11:19:28.665000Z",
    "order": 1,
    "inactive": null,
    "name": "Module 1",
    "description": "Module 1",
    "price": "100.0000000000"
},

最终有效的实施(但我对其不满意的模式)类似于:

class ModuleSerializer(serializers.ModelSerializer):

    class Meta:
        model = Module
        fields = ('id', 'created_at', 'updated_at', 'order', 'inactive',
                  'price', 'name', 'description', 'sub_modules')
        depth = 1

这正确地给了我:

{
    "id": 1,
    "created_at": "2017-02-13T11:19:28.665000Z",
    "updated_at": "2017-02-13T11:19:28.665000Z",
    "order": 1,
    "inactive": null,
    "price": "100.0000000000",
    "name": "Module 1",
    "description": "Module 1",
    "sub_modules": [
        {
            "id": 1,
            "created_at": "2017-02-13T14:16:00.478429Z",
            "updated_at": "2017-02-13T14:16:00.478471Z",
            "order": 1,
            "inactive": null,
            "name": "SubModule 1",
            "description": "SubModule 1",
            "price": "100.0000000",
            "module": 1
        }
    ]
},

为什么我不喜欢这种模式?

使Django Rest Framework成为我选择的REST实现的选择(例如,Flask RESTful),我通常可以依赖我的模式来处理DRY代码和实现一致的单一事实来源。

我希望能够将我的数据层保持在应有的位置 - 在我的模型级别,并且仅更改它并默认情况下将其反馈给序列化程序。显然,当我希望数据转换或不存在时,我会在序列化程序级别上管理异常(或者是一个很好的例子就是保留用户端点数据的password字段)。

如果我必须维护Meta类中的字段值,我本身就是为我的模块实体管理两个事实来源。

我希望能够做什么

我希望sub_modules表达式默认返回我的fields = '__all__'对象。但是,明确指出,DRF文档中默认不会这样做。

所以,我在模块sub_modules上尝试了几个手动serializer.py字段的实现(我认为这是一个可接受的实现,因为它是一种反向关系)。

请记住,以下内容位于模块serializer.py上:

RelatedField

sub_modules = serializers.RelatedField()
结果

AssertionError:关系字段必须提供queryset参数,覆盖get_queryset或设置read_only = True

RelatedField - 有一些参数

sub_modules = serializers.RelatedField(read_only=True)
结果

/ modules /的NotImplementedError 必须为字段sub_modules

实现RelatedField.to_representation()

说什么??

那么,我的最后一个问题是什么?

基本上,我正在寻找一种模式,允许我将序列化程序链接到我的模型并包含反向关系,我不必在serializer.py上明确定义我的字段规范。

我是明确过度暗示的最大倡导者,但在我看来,该模型非常明确。

1 个答案:

答案 0 :(得分:2)

为SubModules创建一个序列化程序,其字段设置为 all 。然后,从ModuleSerializer中引用此序列化器,如下所示:

class ModuleSerializer(serializers.ModelSerializer):
  sub_modules = SubModuleSerializer(many=True)

  class Meta:
      fields = '__all __'
      model = Modules
      depth = 1
  ...

这应该为您提供您正在寻找的嵌套表示,同时保留DRY格式。

Haven实际上已经尝试了这个但是应该工作