diff --git a/aleksis/core/settings.py b/aleksis/core/settings.py index 8e504cf2127382ab7fff0cb85967926d538a02c5..3d39fa2890df626e81961250e1157c4033b23f12 100644 --- a/aleksis/core/settings.py +++ b/aleksis/core/settings.py @@ -196,6 +196,14 @@ TEMPLATES = [ }, ] +# Attention: The following context processors must accept None +# as first argument (in addition to a HttpRequest object) +PDF_CONTEXT_PROCESSORS = [ + "django.template.context_processors.i18n", + "django.template.context_processors.tz", + "aleksis.core.util.core_helpers.custom_information_processor", +] + WSGI_APPLICATION = "aleksis.core.wsgi.application" # Database diff --git a/aleksis/core/util/core_helpers.py b/aleksis/core/util/core_helpers.py index 3dcebe4df7d97fa7fed8db4efda25362bee16210..53ad87a6e71edd3562c642b91e2d4dbf03e17253 100644 --- a/aleksis/core/util/core_helpers.py +++ b/aleksis/core/util/core_helpers.py @@ -3,7 +3,7 @@ from datetime import datetime, timedelta from importlib import import_module, metadata from itertools import groupby from operator import itemgetter -from typing import Any, Callable, Optional, Sequence, Union +from typing import Any, Callable, Dict, Optional, Sequence, Union from warnings import warn from django.conf import settings @@ -14,6 +14,7 @@ from django.http import HttpRequest from django.shortcuts import get_object_or_404 from django.utils import timezone from django.utils.functional import lazy +from django.utils.module_loading import import_string from cache_memoize import cache_memoize @@ -198,7 +199,7 @@ def has_person(obj: Union[HttpRequest, Model]) -> bool: return True -def custom_information_processor(request: HttpRequest) -> dict: +def custom_information_processor(request: Union[HttpRequest, None]) -> dict: """Provide custom information in all templates.""" from ..models import CustomMenu @@ -316,3 +317,12 @@ def get_allowed_object_ids(request: HttpRequest, models: list) -> list: ] return allowed_object_ids + + +def process_custom_context_processors(context_processors: list) -> Dict[str, Any]: + """Process custom context processors.""" + context = {} + processors = tuple(import_string(path) for path in context_processors) + for processor in processors: + context.update(processor(None)) + return context diff --git a/aleksis/core/util/pdf.py b/aleksis/core/util/pdf.py index 3f27680d9d8b3fc569a457ec78a2ce7c154c23d1..03c5fcd47aee7e0a6b8c3b40dca9bbd82568561e 100644 --- a/aleksis/core/util/pdf.py +++ b/aleksis/core/util/pdf.py @@ -1,7 +1,7 @@ import os import subprocess # noqa from tempfile import TemporaryDirectory -from typing import Optional, Tuple +from typing import Optional, Tuple, Union from urllib.parse import urljoin from django.conf import settings @@ -22,6 +22,7 @@ from celery_progress.backend import ProgressRecorder from aleksis.core.celery import app from aleksis.core.models import PDFFile from aleksis.core.util.celery_progress import recorded_task, render_progress_page +from aleksis.core.util.core_helpers import process_custom_context_processors @recorded_task @@ -71,7 +72,10 @@ def generate_pdf_from_template( template_name: str, context: Optional[dict] = None, request: Optional[HttpRequest] = None ) -> Tuple[PDFFile, AsyncResult]: """Start a PDF generation task and return the matching file object and Celery result.""" - html_template = render_to_string(template_name, context, request) + if not request: + processed_context = process_custom_context_processors(settings.PDF_CONTEXT_PROCESSORS) + processed_context.update(context) + html_template = render_to_string(template_name, processed_context, request) file_object = PDFFile.objects.create(html_file=ContentFile(html_template, name="source.html")) @@ -87,7 +91,9 @@ def generate_pdf_from_template( return file_object, result -def render_pdf(request: HttpRequest, template_name: str, context: dict = None) -> HttpResponse: +def render_pdf( + request: Union[HttpRequest, None], template_name: str, context: dict = None +) -> HttpResponse: """Start PDF generation and show progress page. The progress page will redirect to the PDF after completion.