Как реализовать пользовательский рендерер в 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