Возвращает вложенный JSON из моделей с отношениями в Django

#json #django #serialization

#json #django #сериализация

Вопрос:

models.py (упрощенный)

 class Author(models.Model):

    name = models.CharField(max_length=255)
    
    def __str__(self):
        return self.name

    def get_books(self):
        return Book.objects.filter(author=self.pk)


class Book(models.Model):

    name = models.CharField(max_length=255)
    pages = models.IntegerField()
    author = models.ForeignKey(Author, on_delete=models.CASCADE)

    def __str__(self):
        return f'{self.name} from {self.author}'


class Paragraph(models.Model):

    name = models.CharField(max_length=255)
    book = models.ForeignKey(Book, on_delete=models.CASCADE)


    def __str__(self):
        return f'{self.name} from {self.book}'
  

Я хочу вернуть все экземпляры в файле json с этой структурой:

 [
    {
        "name": 'Dumas', 
        "books": {
            "name": "The count of Montecristo",
            "paragraphs": {
                "name": "paragraph_name_1",
                         },
                          {
                "name": "paragraph_name_2",
                         },
                 {
            "name": "The three Musketeers",
            "paragraphs": {
                "name": "paragraph_name",
                         },
]
  

Что я tried:serializers.py

 class AuthorSerializer(serializers.ModelSerializer):

    books = serializers.CharField(source='get_books', read_only=True)

    class Meta:
        model = Author
        fields = ['name', 'books']
  

Это добавляет books ключ, но значение является строковым представлением значений Book (конечно), как я делаю значение сериализованным значением Book ? Я создал BookSerializer .
Примечания:
Я знаю, что могу создать вложенный json, создав сериализатор для Paragraph with depth = 2 , но это будет включать поля, которые мне не нужны (например pages , в Book ), и структура json будет совершенно другой.

Ответ №1:

Вы можете создать вложенный сериализатор как

 class ParagraphSerializer(serializers.ModelSerializer):
    class Meta:
        model = Paragraph
        fields = ("name",)


class BookSerializer(serializers.ModelSerializer):
    paragraphs = ParagraphSerializer(source="paragraph_set", many=True, read_only=True)

    class Meta:
        model = Book
        fields = ("name", "paragraphs")


class AuthorSerializer(serializers.ModelSerializer):
    books = BookSerializer(source="book_set", read_only=True, many=True)

    class Meta:
        model = Author
        fields = ['name', 'books']  

Комментарии:

1. Это работает отлично, но я не понимаю происхождение source=»paragraph_set», я не могу найти его в документах rest framework, можете ли вы объяснить или связать документ, который ссылается на него? Спасибо, я ценю.

2. Вот ссылка на DRF source @JLeno46