mirror of
https://github.com/pretix/pretix.git
synced 2026-08-26 13:14:40 +00:00
improve bg performance by using pdftk
This commit is contained in:
@@ -43,13 +43,12 @@ import dateutil.parser
|
|||||||
from django import forms
|
from django import forms
|
||||||
from django.contrib.staticfiles import finders
|
from django.contrib.staticfiles import finders
|
||||||
from django.core.files import File
|
from django.core.files import File
|
||||||
|
from django.core.files.base import ContentFile
|
||||||
from django.core.files.storage import default_storage
|
from django.core.files.storage import default_storage
|
||||||
from django.db.models import Exists, OuterRef, Q
|
from django.db.models import Exists, OuterRef, Q
|
||||||
from django.db.models.functions import Coalesce
|
from django.db.models.functions import Coalesce
|
||||||
from django.utils.timezone import make_aware
|
from django.utils.timezone import make_aware
|
||||||
from django.utils.translation import gettext as _, gettext_lazy
|
from django.utils.translation import gettext as _, gettext_lazy
|
||||||
from PyPDF2 import Transformation
|
|
||||||
from PyPDF2.generic import RectangleObject
|
|
||||||
from reportlab.lib import pagesizes
|
from reportlab.lib import pagesizes
|
||||||
from reportlab.lib.units import mm
|
from reportlab.lib.units import mm
|
||||||
from reportlab.pdfgen import canvas
|
from reportlab.pdfgen import canvas
|
||||||
@@ -167,7 +166,8 @@ OPTIONS = OrderedDict([
|
|||||||
|
|
||||||
|
|
||||||
def render_pdf(event, positions, opt):
|
def render_pdf(event, positions, opt):
|
||||||
from PyPDF2 import PdfReader, PdfWriter
|
from PyPDF2 import PdfMerger, PdfReader, PdfWriter, Transformation
|
||||||
|
from PyPDF2.generic import RectangleObject
|
||||||
Renderer._register_fonts()
|
Renderer._register_fonts()
|
||||||
|
|
||||||
renderermap = {
|
renderermap = {
|
||||||
@@ -178,71 +178,56 @@ def render_pdf(event, positions, opt):
|
|||||||
default_renderer = _renderer(event, event.badge_layouts.get(default=True))
|
default_renderer = _renderer(event, event.badge_layouts.get(default=True))
|
||||||
except BadgeLayout.DoesNotExist:
|
except BadgeLayout.DoesNotExist:
|
||||||
default_renderer = None
|
default_renderer = None
|
||||||
output_pdf_writer = PdfWriter()
|
|
||||||
|
op_renderers = [(op, renderermap.get(op.item_id, default_renderer)) for op in positions if renderermap.get(op.item_id, default_renderer)]
|
||||||
|
if not len(op_renderers):
|
||||||
|
raise OrderError(_("None of the selected products is configured to print badges."))
|
||||||
|
|
||||||
any = False
|
# render each badge on its own page first
|
||||||
npp = opt['cols'] * opt['rows']
|
merger = PdfMerger()
|
||||||
|
merger.add_metadata({
|
||||||
def render_page(positions):
|
|
||||||
buffer = BytesIO()
|
|
||||||
p = canvas.Canvas(buffer, pagesize=pagesizes.A4)
|
|
||||||
for i, (op, r) in enumerate(positions):
|
|
||||||
offsetx = opt['margins'][3] + (i % opt['cols']) * opt['offsets'][0]
|
|
||||||
offsety = opt['margins'][2] + (opt['rows'] - 1 - i // opt['cols']) * opt['offsets'][1]
|
|
||||||
p.translate(offsetx, offsety)
|
|
||||||
with language(op.order.locale, op.order.event.settings.region):
|
|
||||||
r.draw_page(p, op.order, op, show_page=False, only_page=1)
|
|
||||||
p.translate(-offsetx, -offsety)
|
|
||||||
|
|
||||||
if opt['pagesize']:
|
|
||||||
p.setPageSize(opt['pagesize'])
|
|
||||||
p.showPage()
|
|
||||||
p.save()
|
|
||||||
buffer.seek(0)
|
|
||||||
canvas_pdf_reader = PdfReader(buffer)
|
|
||||||
empty_pdf_page = output_pdf_writer.add_blank_page(
|
|
||||||
width=opt['pagesize'][0] if opt['pagesize'] else positions[0][1].bg_pdf.pages[0].mediabox[2],
|
|
||||||
height=opt['pagesize'][1] if opt['pagesize'] else positions[0][1].bg_pdf.pages[0].mediabox[3],
|
|
||||||
)
|
|
||||||
for i, (op, r) in enumerate(positions):
|
|
||||||
bg_page = copy.copy(r.bg_pdf.pages[0])
|
|
||||||
offsetx = opt['margins'][3] + (i % opt['cols']) * opt['offsets'][0]
|
|
||||||
offsety = opt['margins'][2] + (opt['rows'] - 1 - i // opt['cols']) * opt['offsets'][1]
|
|
||||||
bg_page.add_transformation(Transformation().translate(offsetx, offsety))
|
|
||||||
mb = bg_page.mediabox
|
|
||||||
bg_page.mediabox = RectangleObject((
|
|
||||||
mb.left.as_numeric() + offsetx,
|
|
||||||
mb.bottom.as_numeric() + offsety,
|
|
||||||
mb.right.as_numeric() + offsetx,
|
|
||||||
mb.top.as_numeric() + offsety
|
|
||||||
))
|
|
||||||
bg_page.trimbox = bg_page.mediabox
|
|
||||||
empty_pdf_page.merge_page(bg_page)
|
|
||||||
empty_pdf_page.merge_page(canvas_pdf_reader.pages[0])
|
|
||||||
|
|
||||||
pagebuffer = []
|
|
||||||
outbuffer = BytesIO()
|
|
||||||
for op in positions:
|
|
||||||
r = renderermap.get(op.item_id, default_renderer)
|
|
||||||
if not r:
|
|
||||||
continue
|
|
||||||
any = True
|
|
||||||
pagebuffer.append((op, r))
|
|
||||||
if len(pagebuffer) == npp:
|
|
||||||
render_page(pagebuffer)
|
|
||||||
pagebuffer.clear()
|
|
||||||
|
|
||||||
if pagebuffer:
|
|
||||||
render_page(pagebuffer)
|
|
||||||
|
|
||||||
output_pdf_writer.add_metadata({
|
|
||||||
'/Title': 'Badges',
|
'/Title': 'Badges',
|
||||||
'/Creator': 'pretix',
|
'/Creator': 'pretix',
|
||||||
})
|
})
|
||||||
output_pdf_writer.write(outbuffer)
|
for op, renderer in op_renderers:
|
||||||
|
buffer = BytesIO()
|
||||||
|
page = canvas.Canvas(buffer, pagesize=pagesizes.A4)
|
||||||
|
with language(op.order.locale, op.order.event.settings.region):
|
||||||
|
renderer.draw_page(page, op.order, op)
|
||||||
|
|
||||||
|
if opt['pagesize']:
|
||||||
|
page.setPageSize(opt['pagesize'])
|
||||||
|
page.save()
|
||||||
|
buffer = renderer.render_background(buffer, _('Badge'))
|
||||||
|
merger.append(ContentFile(buffer.read()))
|
||||||
|
|
||||||
|
outbuffer = BytesIO()
|
||||||
|
merger.write(outbuffer)
|
||||||
outbuffer.seek(0)
|
outbuffer.seek(0)
|
||||||
if not any:
|
|
||||||
raise OrderError(_("None of the selected products is configured to print badges."))
|
badges_per_page = opt['cols'] * opt['rows']
|
||||||
|
if (badges_per_page == 1):
|
||||||
|
# no need to place multiple badges on one page
|
||||||
|
return outbuffer
|
||||||
|
|
||||||
|
# place n-up badges/pages per page
|
||||||
|
badges_pdf = PdfReader(outbuffer)
|
||||||
|
nup_pdf = PdfWriter()
|
||||||
|
nup_page = None
|
||||||
|
for i, page in enumerate(badges_pdf.pages):
|
||||||
|
if (i % badges_per_page == 0):
|
||||||
|
nup_page = nup_pdf.add_blank_page(
|
||||||
|
width=opt['pagesize'][0],
|
||||||
|
height=opt['pagesize'][1],
|
||||||
|
)
|
||||||
|
tx = opt['margins'][3] + (i % opt['cols']) * opt['offsets'][0]
|
||||||
|
ty = opt['margins'][2] + (opt['rows'] - 1 - i // opt['cols']) * opt['offsets'][1]
|
||||||
|
nup_page.mergeTranslatedPage(page, tx, ty)
|
||||||
|
|
||||||
|
outbuffer = BytesIO()
|
||||||
|
nup_pdf.write(outbuffer)
|
||||||
|
outbuffer.seek(0)
|
||||||
|
|
||||||
return outbuffer
|
return outbuffer
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user