Circular dependency in serializers

前端 未结 3 1735
有刺的猬
有刺的猬 2020-12-25 13:14

I play with django-rest-framework and I would do following:

from rest_framework import serializers

from .models import Author, Book


class BookSerializer(s         


        
相关标签:
3条回答
  • 2020-12-25 13:27

    A workaround is to use 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')
    
    0 讨论(0)
  • 2020-12-25 13:32

    When the file is imported, it's content is executed from top to bottom. So the line author = AuthorSerializer(many=False) tries to instantiate the AuthorSerializer class before it is defined.

    Even if you could fix the circular dependency problem, it would be bad design. Whenever you serialize an Author, you include a list of all his books, which in turn include the Author object with it's list of books. This will result in another error for exceeding the recursion depth limit.

    What you need to decide is in which direction you want to keep the included serialization: do you want the full Author object in each book serialization, or do you want the list of books with all its information for each Author object?

    The reverse relation can then be included using any form of RelatedField as provided by the Django REST Framework.

    0 讨论(0)
  • 2020-12-25 13:50

    I know the question is pretty old, but I found a simple solution.

    You need to define auxiliary serializers to handle the reference both ways:

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

    This way you can use BookSerializer and AuthorSerializer without infinite circular dependency of a Book having an Author who has Books which have Author who has Books...

    0 讨论(0)
提交回复
热议问题