Круговая зависимость в сериализаторах

Я играю с 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

Кто-нибудь помогает?

Ответы

Ответ 1

Когда файл импортируется, его содержимое выполняется сверху вниз. Поэтому строка author = AuthorSerializer(many=False) пытается создать экземпляр класса AuthorSerializer до его определения.

Даже если вы можете исправить проблему с круговой зависимостью, это будет плохой дизайн. Всякий раз, когда вы сериализуете Автора, вы включаете список всех его книг, которые, в свою очередь, включают объект Author с его списком книг. Это приведет к другой ошибке для превышения предела глубины рекурсии.

Что вам нужно решить, в каком направлении вы хотите сохранить включенную сериализацию: хотите ли вы создать полный авторский объект в каждой сериализации книг или хотите, чтобы список книг со всей его информацией для каждого объекта Author?

Обратное отношение затем может быть включено с использованием любой формы RelatedField как это предусмотрено в Django REST Framework.

Ответ 2

Я знаю, что вопрос довольно старый, но я нашел простое решение.

Вам необходимо определить вспомогательные сериализаторы для обработки ссылки в обоих направлениях:

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

Таким образом, вы можете использовать BookSerializer и AuthorSerializer без бесконечной круговой зависимости Книги, имеющей автора, у которого есть Книги, у которых есть Автор, у которого есть Книги...