DRF нормализует вложенный сериализатор для загрузки отчета Excel с помощью XLSXRenderer

у меня есть ManyToManyполе в моих моделях. В сериализаторе я могу получить вложенные сериализованные данные, но хочу их нормализовать.

models.py

      class Authors(models.Model):
   name = models.CharField(max_length=20)
    
   class Mets:
      db_table = "authors"

class Books(models.Model):
   book_name = models.CharField(max_length=100)
   authors = models.ManyToManyField(Authors, related_names="books")

   class Meta:
      db_table = "books"

serializers.py

      class AuthorSerializer(serializer.ModelSerializer):
   name = serializer.CharField()
   
   class Meta:
      model = Authors
      field = ("name",)

class BooksSerializer(serializer.ModelSerializer):
   authors = AuthorSerializer()
   
   class Meta:
      model = Books
      field = ("book_name", "authors")

Результатом выше будет:

      "result": [
 {
   "book_name": "Sample",
   "authors": [
    {
      "name": "Person 1",
    },
    {
      "name": "Person 2",
    }
   ]
  }
]

Но я хочу вывести что-то вроде этого:

      "result": [
 {
   "book_name": "Sample",
   "author_name": "Person 1",
 },
 {
   "book_name": "Sample",
   "author_name": "Person 2",
 },
]

ОБНОВИТЬ

views.py

      class ReportViewSet(XLSXFileMixin, viewsets.ReadOnlyModelViewSet):
    serializer_class = BookSerializer
    renderer_classes = [XLSXRenderer]
    filename = 'my_export.xlsx'

    def get_queryset(self):
            queryset = Book.objects.all()
            book_id = self.request.query_params.get("pk", None)
            if book_id is not None:
                queryset = queryset.filter(id=book_id)
            return queryset

В отчете Excel должны быть столбцы:, author_name

Но с решением, предоставленным @Klim Bim, я получаю пустой отчет Excel с только именами столбцов: book_name а также authors.

Заранее спасибо.

2 ответа

вы должны использоватьlistвместоget_queryset:

      class ReportViewSet(XLSXFileMixin, ReadOnlyModelViewSet):
    serializer_class = BookSerializer
    renderer_classes = [XLSXRenderer]
    filename = 'my_export.xlsx'
    
    def list(self, request, *arg, **kwargs):
            queryset = Books.objects.filter(#some_filter#)
            return Response(data=self.serializer_class(queryset, many=True).data)

и никогда не забывайте менятьurls.pyкак показано ниже:

      urlpatterns = [
    ...
    path('download-my-file/', ReportViewSet.as_view({'get': 'list'})),
    ....
    ]

Если вы хотите изменить поведение отображения, вы должны переопределить to_representation()

      def to_representation(self, instance):
   data = super().to_representation(instance)
   authors = data.pop('authors')
   retval = list()
   for author in authors:
     retval.append({**data, "author_name": author.get("name")})

   return {"result": retval}