Как реализовать пользовательский рендерер в Django REST framework для экспорта PDF и Excel?

Я реализовал два пользовательских рендера в django rest framework, которые экспортируют данные в Excel или PDF формат. Проблема в том, что я не могу установить имена файлов, когда генерируется ответ.

У меня есть следующие рендеры:

# app/renderers.py
import os
import openpyxl
import pdfkit
import random

from django.template.loader import render_to_string

from rest_framework.renderers import BaseRenderer
from rest_framework.response import Response

# for newer python, do the configuration for pdfkit
config = pdfkit.configuration(wkhtmltopdf=r'path_to_bin/wkhtmltopdf')

class XLSXRenderer(BaseRenderer):
    # ... code truncated 

class PDFRenderer(BaseRenderer):
    media_type = 'application/pdf'
    format = 'pdf'
    charset = 'utf-8'

    def render(self, data, accepted_media_type=None, renderer_context=None):
        if hasattr(data, 'items'):
            for key, value in data.items():
                if key == 'results':
                    html_string = render_to_string('user_mbe/EmployeeList.html', {'header': ('first_name', 'last_name', 'id_number', 'phone_number', 'email', 'job_title'), 'data': [tuple(x.values()) for x in value]})
                    result = pdfkit.from_string(html_string, output_path=False, configuration=config)

                    return result
        return None
# app/views.py

from rest_framework.generics import ListCreateAPIView
from rest_framework.permissions import IsAuthenticated
from rest_framework.renderers import JSONRenderer

from .renderers import PDFRenderer, XLSXRenderer

from .models import Employee
from .serializers.employee import EmployeeSerializer


class EmployeeAPIView(ListAPIView):
    serializer_class = EmployeeSerializer
    # Are these correct here?
    renderer_classes = [PDFRenderer, XLSXRenderer, JSONRenderer]

    def get_queryset(self):
        return Employee.objects.filter(created_by=self.request.user)

    def get(self, request, *args, **kwargs):
        ?? super().get_paginated_response(request, *args, **kwargs)
        ?? unable to set a file name here
        return response

Импортируйте рендереры в свой views.py и вызовите метод list суперкласса, чтобы вызвать пользовательский рендерер. После получения ответа от метода .list вы можете добавить заголовки для имени файла.

# app/views.py
# ...

class EmployeeAPIView(ListAPIView):
    serializer_class = EmployeeSerializer
    # The custom renderers go here
    renderer_classes = [PDFRenderer, XLSXRenderer, JSONRenderer]

    def get_queryset(self):
        return Employee.objects.filter(created_by=self.request.user)

    def get(self, request, *args, **kwargs):
        # call .list method here to invoke the relevant renderer
        # based on the request header accept or query param format type
        response = super().list(request, *args, **kwargs)

        if request.query_params.get("format", "").lower() == 'pdf':
            response.headers = {'Content-Disposition': 'attachment; filename=employee_list.pdf'}
        elif request.query_params.get("format", "").lower() == 'xlsx':
            response.headers = {'Content-Disposition': 'attachment; filename=employee_list.xlsx'}

        return response
Вернуться на верх