Skip to content
Snippets Groups Projects
Commit 75b36c7f authored by jan.bednarik's avatar jan.bednarik
Browse files

elections2021: Fancy PDF export

parent a0892adf
Branches
No related tags found
2 merge requests!304Release,!303Pdf
Showing
with 198 additions and 39 deletions
...@@ -4,4 +4,4 @@ line_length = 88 ...@@ -4,4 +4,4 @@ line_length = 88
multi_line_output = 3 multi_line_output = 3
default_section = "THIRDPARTY" default_section = "THIRDPARTY"
include_trailing_comma = true include_trailing_comma = true
known_third_party = arrow,bleach,bs4,captcha,django,environ,faker,ics,markdown,modelcluster,pirates,pytest,pytz,requests,sentry_sdk,snapshottest,taggit,wagtail,wagtailmetadata,weasyprint known_third_party = PyPDF2,arrow,bleach,bs4,captcha,django,environ,faker,ics,markdown,modelcluster,pirates,pytest,pytz,requests,sentry_sdk,snapshottest,taggit,wagtail,wagtailmetadata,weasyprint
import re import re
from pathlib import Path
from django.core.management.base import BaseCommand from django.core.management.base import BaseCommand, CommandError
from django.template.loader import render_to_string from django.template.loader import render_to_string
from django.utils import timezone from django.utils import timezone
from weasyprint import CSS, HTML from PyPDF2 import PdfFileMerger
from weasyprint import CSS, HTML, default_url_fetcher
from weasyprint.fonts import FontConfiguration
from ...constants import BENEFITS_CHOICES, MINISTRY_CHOICES, MINISTRY_CODES from ...constants import BENEFITS_CHOICES, MINISTRY_CHOICES, MINISTRY_CODES
from ...models import Elections2021ProgramPointPage from ...models import Elections2021ProgramPointPage
FORMAT_PDF = "pdf"
FORMAT_HTML = "html"
STATICS_DIR = (Path(__file__).parent / "../../static/elections2021/pdf/").resolve()
def get_ministry_points(ministry): def get_ministry_points(ministry):
weight = f"weight_ministry_{MINISTRY_CODES[ministry]}" weight = f"weight_ministry_{MINISTRY_CODES[ministry]}"
return Elections2021ProgramPointPage.filter_by_weights([weight]) return Elections2021ProgramPointPage.filter_by_weights([weight])
class Command(BaseCommand): def local_fetcher(url):
def add_arguments(self, parser): if url.startswith("file://"):
parser.add_argument("output", type=str, help=".pdf nebo .html soubor") file = Path(url[7:])
if not file.is_absolute():
file = STATICS_DIR / (url[7:])
return dict(file_obj=file.open(mode="rb"))
return default_url_fetcher(url)
def handle(self, *args, **options):
benefits_titles = {num: title for num, title in BENEFITS_CHOICES} def plain_export(output_file, output_format):
benefits_titles = dict(BENEFITS_CHOICES)
toc = [] toc = []
body = [] body = []
...@@ -48,12 +61,83 @@ class Command(BaseCommand): ...@@ -48,12 +61,83 @@ class Command(BaseCommand):
}, },
) )
if options["output"].endswith(".pdf"): if output_format == FORMAT_PDF:
font_config = FontConfiguration()
html = HTML(string=content) html = HTML(string=content)
css = CSS(string="@page { size: A4; margin: 1cm; }") css = CSS(
html.write_pdf(options["output"], stylesheets=[css]) string="""
elif options["output"].endswith(".html"): @page {
with open(options["output"], "w") as file: size: A4;
margin: 1cm;
}
@font-face {
font-family: "Roboto Condensed";
src: url("https://github.com/google/fonts/blob/main/apache/roboto/static/RobotoCondensed-Regular.ttf?raw=true");
}
""",
font_config=font_config,
)
html.write_pdf(output_file, stylesheets=[css], font_config=font_config)
elif output_format == FORMAT_HTML:
with open(output_file, "w") as file:
file.write(content) file.write(content)
def fancy_export(output_file):
tmp_file = f"{output_file}.tmp"
benefits_titles = dict(BENEFITS_CHOICES)
points = []
for ministry, title in MINISTRY_CHOICES:
for page in get_ministry_points(ministry):
value = render_to_string(
"elections2021/export_program_point_fancy.html",
{"page": page, "benefits_titles": benefits_titles},
)
value = re.sub(r'href="#', f'href="#{page.id}_', value)
value = re.sub(r'id="', f'id="{page.id}_', value)
points.append(value)
content = render_to_string(
"elections2021/export_program_fancy.html", {"points": points}
)
font_config = FontConfiguration()
html = HTML(string=content, url_fetcher=local_fetcher)
css = CSS(str(STATICS_DIR / "style.css"), font_config=font_config)
document = html.render(stylesheets=[css], font_config=font_config)
document.write_pdf(tmp_file)
merger = PdfFileMerger()
merger.append(str(STATICS_DIR / "beginning.pdf"))
merger.append(tmp_file, pages=(2, len(document.pages)))
merger.append(str(STATICS_DIR / "ending.pdf"))
merger.write(output_file)
merger.close()
Path(tmp_file).unlink()
class Command(BaseCommand):
def add_arguments(self, parser):
parser.add_argument("output", type=str, help=".pdf nebo .html soubor")
parser.add_argument("--fancy", action="store_true")
def handle(self, *args, **options):
output_file = options["output"]
if output_file.endswith(".pdf"):
output_format = FORMAT_PDF
elif output_file.endswith(".html"):
output_format = FORMAT_HTML
else:
raise CommandError("Jako výstup zadej soubor .html nebo .pdf")
if options["fancy"]:
if output_format != FORMAT_PDF:
raise CommandError("Fancy export lze udělat jen do .pdf")
fancy_export(output_file)
else: else:
print("ERROR: Jako výstup zadej soubor .html nebo .pdf") plain_export(output_file, output_format)
File added
File added
File added
File added
File added
File added
File added
File added
File added
File added
File added
File added
File added
File added
File added
File added
This diff is collapsed.
File added
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment