How to export to PDF in Django?

1

I'm using Django 1.8 and I want to export an HTML document to PDF, for this I use wkhtmltopdf, in addition to other libraries I had to import the following and the file view.py was like this:

from django.views.generic import DetailView
from wkhtmltopdf.views import PDFTemplateResponse

class MyPDFView(DetailView):
    model1 = Contrato
    model2 = Servicio_Contratado
    template = 'acuerdos.html'
    context = {'titulo': 'CubanCloud'}
    def get(self, request, *args, **kwargs):
        self.context['entry'] = self.get_object()
        response = PDFTemplateResponse(request=request,
            template=self.template,
            filename="Contrato CubanCloud.pdf",
            context=self.context,
            footer_template="footer.html",
            show_content_in_browser=True,
            cmd_options={'margin-top': 15,
                'margin-bottom': 20,
                'default-header': True,
                'header-left':Cubancloud',
                'footer-line': True,
            },
      )
      return response

The url was like this:

url(r'^/pdf$', views.MyPDFView.as_view(), name='pagina_detalle'),

I call the operation using a link in the template, which is as follows:

<a href="{% url "pagina_detalle" %}"> Generar PDF de</a>

When I click on the link I get the following error message:

ImproperlyConfigured at /cubancloud/pdf
MyPDFView is missing a QuerySet. Define MyPDFView.model, MyPDFView.queryset, or override MyPDFView.get_queryset().
    
asked by Roberto Cárdenas 04.05.2017 в 21:03
source

2 answers

1

I decided to use ReportLab and it went very well. Here I leave the code I hope it serves:

class ContratoToPDF(View):
def cabecera(self, pdf):
    # Utilizamos el archivo logo_django.png que está guardado en la carpeta media/imagenes
    archivo_imagen=settings.MEDIA_ROOT + '/LogoCubanCloudPDF.png'
    # Definimos el tamaño de la imagen a cargar y las coordenadas correspondientes
    pdf.drawImage(archivo_imagen, 40, 750, 500, 90, preserveAspectRatio=True)
    # Establecemos el tamaño de letra en 16 y el tipo de letra Helvetica
    pdf.setFont("Helvetica", 16)
    # Dibujamos una cadena en la ubicación X,Y especificada
    pdf.drawString(230, 780, u"Contrato de CubanCloud")

def tabla(self, pdf, y):
    id_cont=2
    encabezados=('Servicios Contratados', 'No. Contrato', 'Plan', 'Precio')
    lista_nombres=[]
    for var in Servicio_Contratado.objects.filter(contrato_id=id_cont):
        lista_nombres.append((var.nombre, var.pk, str(var.plazo) + " días", var.precio))
    detalle_orden=Table([encabezados] + lista_nombres)
    detalle_orden.wrapOn(pdf, 800, 600)
    # Definimos la coordenada donde se dibujará la tabla
    detalle_orden.drawOn(pdf, 34, y)

def acls(self,pdf,request,y):
    pdf.setFont("Helvetica", 10)
    pdf.drawCentredString(316,y,u"ACUERDOS DE NIVEL DE SERVICIO")


def info_user(self,pdf,request):
    id_cont=2
    pdf.setFont("Helvetica", 10)
    # Dibujamos una cadena en la ubicación X,Y especificada
    pdf.drawString(40, 740, u"NOMBRE DEL CLIENTE: "+ request.user.first_name + u" " + request.user.last_name)
    pdf.drawString(40, 725, u"NOMBRE DE USUARIO : " + request.user.username)
    pdf.drawString(40, 710, u"E-MAIL: " + request.user.email)
    pdf.drawString(40, 695, u"NUMERO DE CONTRATO: " + str(id_cont))

def get(self, request, *args, **kwargs):
    # Indicamos el tipo de contenido a devolver, en este caso un pdf
    response=HttpResponse(content_type='application/pdf')
    # La clase io.BytesIO permite tratar un array de bytes como un fichero binario, se utiliza como almacenamiento temporal
    buffer=BytesIO()
    # Canvas nos permite hacer el reporte con coordenadas X y Y
    pdf=canvas.Canvas(buffer)
    # Llamo al método cabecera donde están definidos los datos que aparecen en la cabecera del reporte.
    self.cabecera(pdf)
    y=600
    self.tabla(pdf, y)
    self.info_user(pdf,request)
    self.acls(pdf,request,y-15)
    # Con show page hacemos un corte de página para pasar a la siguiente
    pdf.showPage()
    pdf.save()
    pdf=buffer.getvalue()
    buffer.close()
    response.write(pdf)
    return response
    
answered by 08.05.2017 в 17:25
0

You are using DetailView that needs two things to work: a model and an identifier.

Basically what you would have to do is redefine get_queryset() instead of get() . Neither do you need model1 and model2 , because Django does not know what to do with those variables, what it occupies is model .

You can check the class at this link: link

    
answered by 05.05.2017 в 16:14