0

I need to be able to use a static image as watermark when printing a pdf from a django template using django-wkhtmltopdf. I was trying using the following code, but the document has several pages and the background does not apply to every page individually. Instead it tries to apply the background to the whole document, and as a result the images takes a bigger size, covering all pages. How can I apply the image as a background to every page individually? Here is my code:

  1. Defining a background using CSS

    body { background-image: url("{{ watermark_logos }}"); background-size: cover; }

  2. Generating a pdf with django-wkhtml2pdf. Note that the "cmd_options" represent the parameters for wkhtmltopdf

    response = PDFTemplateResponse(request=request,
                                   template=template_to_use,
                                   filename="Ficha proyecto {}.pdf".format(project.get_numero_trabajo),
                                   context= data,
                                   show_content_in_browser=False,
                                   cmd_options={  
                                    'margin-top':0,
                                    'margin-bottom':0,
                                    'margin-left':0,
                                    'margin-right':0,
                                   "zoom":1,
                                   "viewport-size" :"1366x513",
                                   'javascript-delay':1000,
                                   'enable-local-file-access':True,
                                   'footer-center' :'[page]/[topage]',
                                   "no-stop-slow-scripts":True},
                                   )
    

Here is the watermark I want to use for every page

watermark I want to use

Ernesto Ruiz
  • 736
  • 9
  • 31
  • Could you give an example of the css code you used? I updated my question cause I have a problem.The document has several pages and the background does not apply to every page individually. Instead it tries to apply the background to the whole document, and as a result the images takes a bigger size, covering all pages. The reult is not pretty – Ernesto Ruiz Feb 23 '23 at 17:23

2 Answers2

0

In your case, the easiest way is to substitute the text created on a separate canvas.

     packet = io.BytesIO()
     existing_pdf = PdfFileReader(open(os.path.join('media', 'your-directory'), 'rb')) # Opening pdf-file
     output = PdfFileWriter()

     can = canvas.Canvas(packet, pagesize=(1,1)) # Creating new canvas for text
     can.setFillColorRGB(255, 255, 255) # Set watermark color
     can.drawString(1, 1, 'YOUR WATERMARK TEXT') # Paste your text into canvas
     can.save()
     # Paste canvas to pdf
     packet.seek(0)
     new_pdf = PdfFileReader(packet)
     pages = existing_pdf.getPage(-1).mergePage(new_pdf.getPage(0))
     output.appendPagesFromReader(existing_pdf)


     new_name = 'filename.pdf'
     new_url = os.path.join('media', 'your-directory')
BIcrypt
  • 1
  • 2
0

In comments you indicate you need a variable means to use wkhtml with different fixed size backgrounds, here I have set a page with and one without but it could be either the same or a different image, per page.

The key to placing images in a PDF is to constrain an image so it cannot exceed the page boundary, HOWEVER, Html does not stop images or text flowing beyond the page boundary and either it gets clipped or overflows.

There are several scalars involved as un-managed wkhtml prefers images to be 120 ppi, so here for A4 (wkhtml will set page to rounded off imperial /MediaBox [0 0 595 842] = 209.9 mm x 297.0) I have pre-set the image to 993 x 1404. (should have been 992 x 1,403 but oddly see the way its slightly adapted by usage!)

Thus, actually in the final PDF its clipped to !

/Type /XObject
/Subtype /Image
/Width 989
/Height 1403

But that's not the only consideration, as when subject to css there are other factors such that in testing the css itself needs minor adjustment to compensate using -40 px in both directions, which seem to be related to my use of 20 px padding! as without that I need the full 990 x 1403 (/Image /Width 990 /Height 1403

With 20 px padding

  width: 949px;
  height: 1363px;

enter image description here

Thus as a starting template try :-

wkhtmltopdf --enable-local-file-access -T "0mm" -L "0mm" -R "0mm" -B "0mm" test.html test.pdf
<HTML>
<HEAD>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=windows-1252">
<style>
html { border: 0; margin: 0; }
body { border: 0; margin: 0; font-family: Verdana,sans-serif;}
h1, h3 {
  text-align: center;
  text-transform: uppercase;
  color: #FF40C0;
}
div { margin-left: 20mm; margin-right: 20mm; }
span.ImgA4P {
  page-break-after: auto;
  display: inline-block;
  border: 0; 
  margin: 0;   
  padding: 20;
  width: 949px;
  height: 1363px;
  background-image: url("SipoW.png");
  background-position: left top;
}
span.NoImgA4P {
  page-break-after: auto;
  display: inline-block;
  border: 0; 
  margin: 0;   
  padding: 20;
  width: 949px;
  height: 1363px;
}
</style>
</HEAD>
<BODY LINK="#0000ff" VLINK="#800080">

<span class="ImgA4P">
<P>Hello World</P>
<div><h3>Now is the 1st winter of our disposition</h3></div>
<div>   Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</div>
</span>
<span class="NoImgA4P">
<P>Hello World</P>
<div><h3>Now is the 2nd winter of our disposition</h3></div>
<div>   Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</div>
</span>
</BODY>
</HTML>

If all you want is the same one image per page, it is far simpler as we attach to body NOT BOTH. <span class="page">

enter image description here

body {
  border: 0;
  margin: 0;
  font-family: Verdana,sans-serif;
  background-image: url("SipoW.png");
  background-position: left top;
}
h1, h3 {
  text-align: center;
  text-transform: uppercase;
  color: #FF40C0;
}
div { margin-left: 20mm; margin-right: 20mm; }
span.page {
  page-break-after: auto;
  display: inline-block;
  width: 990px;
  height: 1403px;
  border: 0; 
  margin: 0;   
  padding: 0;
}
K J
  • 8,045
  • 3
  • 14
  • 36