序列化程序中的循环依赖

Tom*_*chý 21 api django rest django-rest-framework

我玩django-rest-framework,我会做以下事情:

from rest_framework import serializers

from .models import Author, Book


class BookSerializer(serializers.ModelSerializer):
    author = AuthorSerializer(many=False)

    class Meta:
        model = Book
        fields = ('slug', 'name')


class AuthorSerializer(serializers.ModelSerializer):
    books = BookSerializer(many=True)

    class Meta:
        model = Author
        fields = ('slug', 'name', 'books')
Run Code Online (Sandbox Code Playgroud)

但它失败了.

NameError at /api/books/authors/
name 'AuthorSerializer' is not defined
Run Code Online (Sandbox Code Playgroud)

有人帮忙吗?

knb*_*nbk 16

导入文件时,它的内容从上到下执行.因此,该行author = AuthorSerializer(many=False)尝试AuthorSerializer在定义之前实例化该类.

即使您可以解决循环依赖问题,也可能是糟糕的设计.每当您序列化作者时,您都会列出他所有书籍的列表,而这些书籍又包含作者对象及其书籍列表.这将导致超出递归深度限制的另一个错误.

您需要决定的是保持包含序列化的方向:您是否希望每个书籍序列化中都有完整的Author对象,或者您是否希望每个Author对象的书籍列表及其所有信息?

然后可以使用RelatedField Django REST Framework提供的任何形式包含反向关系.


Fid*_*idd 10

我知道这个问题很老了,但我找到了一个简单的解决方案。

您需要定义辅助序列化程序以两种方式处理引用:

class BookUnrelatedSerializer(serializers.ModelSerializer):
    class Meta:
        model = Book
        fields = ('slug', 'name')


class AuthorUnrelatedSerializer(serializers.ModelSerializer):
    class Meta:
        model = Author
        fields = ('slug', 'name')


class BookSerializer(BookUnrelatedSerializer):
    author = AuthorUnrelatedSerializer()

    class Meta(BookUnrelatedSerializer.Meta):
        fields = (*BookUnrelatedSerializer.Meta.fields, 'author')


class AuthorSerializer(AuthorUnrelatedSerializer):
    book_set = BookUnrelatedSerializer(many = True)

    class Meta(AuthorUnrelatedSerializer.Meta):
        fields = (*AuthorUnrelatedSerializer.Meta.fields, 'book_set')
Run Code Online (Sandbox Code Playgroud)

这样,您就可以使用BookSerializer,并AuthorSerializer无需谁拥有它有作者谁拥有书籍的作者一本书的无限循环依赖...


小智 7

一种解决方法是使用serializers.SerializerMethodField()

from rest_framework import serializers

from .models import Author, Book


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

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

    def get_author(self, obj):
        return AuthorSerializer(obj.author).data


class AuthorSerializer(serializers.ModelSerializer):
    books = BookSerializer(many=True)

    class Meta:
        model = Author
        fields = ('slug', 'name', 'books')
Run Code Online (Sandbox Code Playgroud)