You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
179 lines
5.1 KiB
Python
179 lines
5.1 KiB
Python
from datetime import datetime
|
|
import unicodedata
|
|
import os
|
|
import subprocess
|
|
import time
|
|
import glob
|
|
from io import BytesIO
|
|
from pypdf import PdfReader, PdfWriter, PageObject
|
|
from django import template
|
|
from django.template.loader import get_template
|
|
from django.conf import settings
|
|
from django.http import HttpResponse, HttpResponseRedirect
|
|
from wsgiref.util import FileWrapper
|
|
from contrib.media import media_path, media_dir, serve_media, ensure_media_dir, find_template
|
|
from utils import normalize_filename
|
|
from PIL import Image
|
|
|
|
|
|
def serve_pdf(filename_pdf):
|
|
return serve_media(filename_pdf, 'application/pdf')
|
|
|
|
|
|
def generate_tex(name, template_path, context, date=None):
|
|
filename = normalize_filename(name, date=date)
|
|
filename_tex = filename + '.tex'
|
|
|
|
tmpl = get_template(template_path)
|
|
res = tmpl.render(dict(context, creation_date=datetime.today().strftime('%d.%m.%Y')))
|
|
|
|
ensure_media_dir()
|
|
|
|
with open(media_path(filename_tex), 'w', encoding='utf-8') as f:
|
|
f.write(res)
|
|
return filename
|
|
|
|
|
|
def render_docx(name, template_path, context, date=None, save_only=False):
|
|
filename = generate_tex(name, template_path, context, date=date)
|
|
filename_tex = filename + '.tex'
|
|
filename_docx = filename + '.docx'
|
|
oldwd = os.getcwd()
|
|
os.chdir(media_dir())
|
|
subprocess.call(['pandoc', filename_tex, '-o', filename_docx])
|
|
time.sleep(1)
|
|
os.chdir(oldwd)
|
|
if save_only:
|
|
return filename_docx
|
|
return serve_media(filename_docx, 'application/docx')
|
|
|
|
def render_tex_with_attachments(name, template_path, context, attachments, save_only=False):
|
|
|
|
rendered_pdf = render_tex(name, template_path, context, save_only=True)
|
|
|
|
reader = PdfReader(media_path(rendered_pdf))
|
|
writer = PdfWriter()
|
|
writer.append(reader)
|
|
|
|
pdf_add_attachments(writer, attachments)
|
|
|
|
with open(media_path(rendered_pdf), 'wb') as output_stream:
|
|
writer.write(output_stream)
|
|
|
|
if save_only:
|
|
return rendered_pdf
|
|
return serve_pdf(rendered_pdf)
|
|
|
|
|
|
def render_tex(name, template_path, context, date=None, save_only=False):
|
|
filename = generate_tex(name, template_path, context, date=date)
|
|
filename_tex = filename + '.tex'
|
|
filename_pdf = filename + '.pdf'
|
|
# compile using pdflatex
|
|
oldwd = os.getcwd()
|
|
os.chdir(media_dir())
|
|
subprocess.call(['pdflatex', '-halt-on-error',filename_tex])
|
|
time.sleep(1)
|
|
|
|
# do some cleanup
|
|
for f in glob.glob('*.log'):
|
|
os.remove(f)
|
|
for f in glob.glob('*.aux'):
|
|
os.remove(f)
|
|
#os.remove(filename_tex)
|
|
#os.remove(filename_table)
|
|
|
|
os.chdir(oldwd)
|
|
|
|
if save_only:
|
|
return filename_pdf
|
|
return serve_pdf(filename_pdf)
|
|
|
|
|
|
def pdf_add_attachments(pdf_writer, attachments):
|
|
for fp in attachments:
|
|
try:
|
|
if fp.endswith(".pdf"):
|
|
# append pdf directly
|
|
img_pdf = PdfReader(fp)
|
|
else:
|
|
# convert ensures that png files with an alpha channel can be appended
|
|
img = Image.open(fp).convert("RGB")
|
|
img_io = BytesIO()
|
|
img.save(img_io, "pdf")
|
|
img_io.seek(0)
|
|
img_pdf = PdfReader(img_io)
|
|
img_pdf_scaled = scale_pdf_to_a4(img_pdf)
|
|
pdf_writer.append(img_pdf_scaled)
|
|
|
|
except Exception as e:
|
|
print("Could not add image", fp)
|
|
print(e)
|
|
|
|
|
|
def scale_pdf_page_to_a4(page):
|
|
A4_WIDTH, A4_HEIGHT = 595, 842
|
|
|
|
page_width = page.mediabox.width
|
|
page_height = page.mediabox.height
|
|
scale_x = A4_WIDTH / page_width
|
|
scale_y = A4_HEIGHT / page_height
|
|
scale_factor = min(scale_x, scale_y)
|
|
|
|
new_page = PageObject.create_blank_page(width=A4_WIDTH, height=A4_HEIGHT)
|
|
page.scale_by(scale_factor)
|
|
x_offset = (A4_WIDTH - page.mediabox.width) / 2
|
|
y_offset = (A4_HEIGHT - page.mediabox.height) / 2
|
|
new_page.merge_translated_page(page, x_offset, y_offset)
|
|
|
|
return new_page
|
|
|
|
|
|
def scale_pdf_to_a4(pdf):
|
|
scaled_pdf = PdfWriter()
|
|
for page in pdf.pages:
|
|
scaled_pdf.add_page(scale_pdf_page_to_a4(page))
|
|
|
|
return scaled_pdf
|
|
|
|
|
|
def fill_pdf_form(name, template_path, fields, attachments=[], date=None, save_only=False):
|
|
filename = normalize_filename(name, date=date)
|
|
filename_pdf = filename + '.pdf'
|
|
|
|
path = find_template(template_path)
|
|
|
|
ensure_media_dir()
|
|
|
|
reader = PdfReader(path)
|
|
writer = PdfWriter()
|
|
|
|
writer.append(reader)
|
|
|
|
writer.update_page_form_field_values(None, fields, auto_regenerate=False)
|
|
|
|
pdf_add_attachments(writer, attachments)
|
|
|
|
with open(media_path(filename_pdf), 'wb') as output_stream:
|
|
writer.write(output_stream)
|
|
|
|
if save_only:
|
|
return filename_pdf
|
|
return serve_pdf(filename_pdf)
|
|
|
|
|
|
def merge_pdfs(name, filenames, date=None, save_only=False):
|
|
merger = PdfWriter()
|
|
|
|
for pdf in filenames:
|
|
merger.append(media_path(pdf))
|
|
|
|
filename = normalize_filename(name, date=date)
|
|
filename_pdf = filename + ".pdf"
|
|
merger.write(media_path(filename_pdf))
|
|
merger.close()
|
|
|
|
if save_only:
|
|
return filename_pdf
|
|
return serve_pdf(filename_pdf)
|