Tengo un gran conjunto de datos para el que tengo que generar CSV y PDF. Con CSV, uso esta guía: https://docs.djangoproject.com/en/3.1/howto/outputting-csv/
import csv from django.http import StreamingHttpResponse class Echo: """An object that implements just the write method of the file-like interface. """ def write(self, value): """Write the value by returning it, instead of storing in a buffer.""" return value def some_streaming_csv_view(request): """A view that streams a large CSV file.""" # Generate a sequence of rows. The range is based on the maximum number of # rows that can be handled by a single sheet in most spreadsheet # applications. rows = (["Row {}".format(idx), str(idx)] for idx in range(65536)) pseudo_buffer = Echo() writer = csv.writer(pseudo_buffer) response = StreamingHttpResponse((writer.writerow(row) for row in rows), content_type="text/csv") response['Content-Disposition'] = 'attachment; filename="somefilename.csv"' return response Funciona muy bien. Sin embargo, no puedo encontrar nada que se pueda hacer para PDF. ¿Puede? Yo uso render_to_pdf así como también uso una plantilla para PDF.
Piense en CSV como una ensalada de frutas. Puedes rebanar plátanos en una olla grande, agregar algunas toronjas, un poco de piña, ... y luego dividir el conjunto en porciones individuales que llevas a la mesa (esto es: generas tu archivo CSV y luego lo envías a el cliente). Pero también podrías hacer porciones individuales directamente: Corta unas rodajas de plátano en un bol pequeño, añade unos pomelos, un poco de piña,... trae este bol pequeño a la mesa, y repite el proceso para otras porciones individuales (esto es: genera su archivo CSV y lo envía parte por parte al cliente a medida que lo genera).
Bueno, si CSV es una ensalada de frutas, entonces PDF es un pastel. Tienes que mezclar todos sus ingredientes y ponerlo en el horno. Esto significa que no puedes traer una porción del pastel a la mesa hasta que hayas horneado todo el pastel. Del mismo modo, no puede comenzar a enviar su archivo PDF al cliente hasta que se haya generado por completo.
Entonces, para responder a su pregunta, esto ( response = StreamingHttpResponse((writer.writerow(row) for row in rows), content_type="text/csv") ) no se puede hacer para PDF.
Sin embargo, una vez que se genera su archivo , puede transmitirlo al cliente usando FileResponse como se menciona en otras respuestas.
Si su problema es que la generación del PDF lleva demasiado tiempo (y puede provocar un error de tiempo de espera, por ejemplo), aquí hay algunas cosas que debe considerar:
¿Has probado FileResponse ?
Algo como esto debería funcionar, es básicamente lo que puedes encontrar en el documento de Django :
import io from django.http import FileResponse from reportlab.pdfgen import canvas def stream_pdf(request): buffer = io.BytesIO() p = canvas.Canvas(buffer) p.drawString(10, 10, "Hello world.") p.showPage() p.save() buffer.seek(io.SEEK_SET) return FileResponse(buffer, as_attachment=True, filename='helloworld.pdf')Mirando el enlace que proporcionó, proporciona un enlace a una página sobre cómo crear y enviar archivos pdf dinámicamente usando reportlab .
import io from django.http import FileResponse from reportlab.pdfgen import canvas def some_view(request): # Create a file-like buffer to receive PDF data. buffer = io.BytesIO() # Create the PDF object, using the buffer as its "file." p = canvas.Canvas(buffer) # Draw things on the PDF. Here's where the PDF generation happens. # See the ReportLab documentation for the full list of functionality. p.drawString(100, 100, "Hello world.") # Close the PDF object cleanly, and we're done. p.showPage() p.save() # FileResponse sets the Content-Disposition header so that browsers # present the option to save the file. buffer.seek(0) return FileResponse(buffer, as_attachment=True, filename='hello.pdf')Aquí hay un enlace a la documentación de la API de reportlab . Es un poco largo y está almacenado en un pdf de una sola página molesto para navegar, pero debería ponerlo en funcionamiento y poder formatear bien los PDF como desee.