序列化程序中的循环依赖

时间:2014-03-23 12:27:12

标签: django api 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')

但它失败了。

NameError at /api/books/authors/
name 'AuthorSerializer' is not defined

有人帮忙吗?

3 个答案:

答案 0 :(得分:15)

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

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

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

然后可以使用任何形式的RelatedField as provided by the Django REST Framework来包含反向关系。

答案 1 :(得分:4)

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

您需要定义辅助序列化程序以双向处理引用:

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')

通过这种方式,您可以使用BookSerializerAuthorSerializer,而无需具有作者的图书的无限循环依赖关系,该图书的作者具有书籍的作者...

答案 2 :(得分:2)

一种解决方法是使用 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')