Select Git revision
export_program.py

jan.bednarik authored
export_program.py 5.12 KiB
import re
from datetime import date
from io import BytesIO
from pathlib import Path
from django.core.management.base import BaseCommand, CommandError
from django.template.loader import render_to_string
from django.utils import timezone
from PyPDF2 import PdfFileMerger
from weasyprint import CSS, HTML, default_url_fetcher
from weasyprint.text.fonts import FontConfiguration
from ...constants import BENEFITS_CHOICES, MINISTRY_CHOICES, MINISTRY_CODES
from ...models import Elections2021ProgramPointPage
FORMAT_PDF = "pdf"
FORMAT_HTML = "html"
STATICS_DIR = (Path(__file__).parent / "../../static/elections2021/pdf/").resolve()
def get_ministry_points(ministry):
weight = f"weight_ministry_{MINISTRY_CODES[ministry]}"
return Elections2021ProgramPointPage.filter_by_weights([weight])
def local_fetcher(url):
if url.startswith("file://"):
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 plain_export(output_file, output_format):
benefits_titles = dict(BENEFITS_CHOICES)
toc = []
body = []
for ministry, title in MINISTRY_CHOICES:
sub_toc = []
points = []
for page in get_ministry_points(ministry):
value = render_to_string(
"elections2021/export_program_point.html",
{"page": page, "benefits_titles": benefits_titles},
)
value = re.sub(r'href="#zdroje"', f'href="#zdroje_{page.id}"', value)
points.append(value)
sub_toc.append({"anchor": page.slug, "title": page.title})
body.append({"anchor": ministry, "title": title, "points": points})
toc.append({"anchor": ministry, "title": title, "sub_toc": sub_toc})
content = render_to_string(
"elections2021/export_program.html",
{
"toc": toc,
"body": body,
"now": timezone.localtime().strftime("%d.%m.%Y %H:%M"),
},
)
if output_format == FORMAT_PDF:
font_config = FontConfiguration()
html = HTML(string=content)
css = CSS(
string="""
@page {
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)
def fancy_export(output_file, ministry=None):
tmp_file = f"{output_file}.tmp"
benefits_titles = dict(BENEFITS_CHOICES)
if ministry is None:
pages = (
Elections2021ProgramPointPage.objects.live()
.specific()
.order_by("-default_order")
)
else:
pages = get_ministry_points(ministry)
points = []
for page in pages:
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}
)
today = date.today().strftime("%d.%m.%Y")
extra_css = '@page { @bottom-left { content: "%s" }}' % today
font_config = FontConfiguration()
html = HTML(string=content, url_fetcher=local_fetcher)
css = CSS(str(STATICS_DIR / "style.css"), font_config=font_config)
css2 = CSS(BytesIO(extra_css.encode("utf-8")), font_config=font_config)
document = html.render(stylesheets=[css, css2], 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")
parser.add_argument("--ministry", type=str)
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, options["ministry"])
else:
plain_export(output_file, output_format)