Django DRF - 以线性形式序列化外键关系

时间:2018-02-07 15:07:52

标签: django django-rest-framework

我正在使用DRF来启动我的Django REST API。考虑以下模型:

class Author(models.Model):
   name = CharField(...)

class Book(models.Model)
   author = ForeignKey(Ablum)
   title = CharField(...)

我想要的输出应该是一个线性JSON,如下所示:

[
   {
      "name": "Jack London",
      "title": "White fang"
   }
   {
     "name": "Jack London",
     "title": "Martin Iden"
   }
   {
      "name": "Charles Dickens",
      "title": "David Coperfield" 
    }
    {
      "name": "Charles Dickens",
      "title": "Oliver Twist"
    }
]

我使用相应的序列化器

完成了结果
class BookSerializer(serializers.ModelSerializer):
    author = serializers.CharField(source='album.author')

    class Meta:
        model = Book
        depth = 1
        fields = ('author', 'title ')

...但问题是这个解决方案在干燥方面非常脏。每次我向作者添加新字段时,我都希望它也出现在Book中。有没有办法告诉Django包含相关模型的所有字段?或者

我也尝试了以下方法:

class BookSerializer(serializers.ModelSerializer):
        author = CalendarEventSerializer(read_only = True)

        class Meta:
           model = Book
           depth = 1
           fields = ('author', 'title ')

但是有了这个,我最终得到了这样的嵌套JSON结构:

[        {           “名字”:“杰克伦敦”,           “作者”:{...}        },        ... ]

不符合我的需要。 所以,问题是:是否有比我在这里做的更干燥的方法?

2 个答案:

答案 0 :(得分:0)

只需为您编写自定义get_author方法。

class BookSerializer(serializers.ModelSerializer):
    author = serializers.SerializerMethodField()

    def get_author(self, instance):
        # write whatever you want
        return author

    class Meta:
        model = Book
        fields = ('author', 'title ')

答案 1 :(得分:0)

添加序列化方法get_author_name。因此,您将获得您想要的数据。在序列化程序中添加author字段并将其设置为 write_only ,以便您可以使用相同的序列化程序创建和更新

class BookSerializer(serializers.ModelSerializer):
    author_name = serializers.serializers.SerializerMethodField()

    class Meta:
        model = Book
        fields = ('author', 'author_name', 'title')
        extra_kwargs = {
            'author': {'write_only': True},
        }

    def get_auther_name(self, obj):
        return obj.auther.name

你的json将是

[
   {
      "auther_name": "Jack London",
      "title": "White fang"
   }
   {
     "auther_name": "Jack London",
     "title": "Martin Iden"
   }
   {
      "auther_name": "Charles Dickens",
      "title": "David Coperfield" 
    }
    {
      "auther_name": "Charles Dickens",
      "title": "Oliver Twist"
    }
]

注意:不要覆盖author字段。如果是这样,您无法使用序列化程序添加或更新

更新(根据评论)

如果您不想更改结果字段,请使用

class BookSerializer(serializers.ModelSerializer):
    author = serializers.serializers.SerializerMethodField()
    author_obj = serializers.PrimaryKeyRelatedField(queryset=Author.objects.all(), required=True, write_only=True)

    class Meta:
        model = Book
        fields = ('author_obj', 'author', 'title')        

    def get_auther(self, obj):
        return obj.auther.name

因此结果将与您想要的结果相同。要添加或更新,请提供作者的id以在请求中提交author_obj