diff --git a/InvenTree/InvenTree/settings.py b/InvenTree/InvenTree/settings.py index 6cadb09150..e325e092da 100644 --- a/InvenTree/InvenTree/settings.py +++ b/InvenTree/InvenTree/settings.py @@ -148,6 +148,7 @@ INSTALLED_APPS = [ 'mptt', # Modified Preorder Tree Traversal 'markdownx', # Markdown editing 'markdownify', # Markdown template rendering + 'django_tex', # LaTeX output ] LOGGING = { @@ -199,6 +200,14 @@ TEMPLATES = [ ], }, }, + # Backend for LaTeX report rendering + { + 'NAME': 'tex', + 'BACKEND': 'django_tex.engine.TeXEngine', + 'DIRS': [ + os.path.join(MEDIA_ROOT, 'report'), + ] + }, ] REST_FRAMEWORK = { @@ -341,6 +350,17 @@ DATE_INPUT_FORMATS = [ "%Y-%m-%d", ] +# LaTeX rendering settings (django-tex) +latex_settings = CONFIG.get('latex', {}) + +# Set the latex interpreter in the config.yaml settings file +LATEX_INTERPRETER = latex_settings.get('interpreter', 'pdflatex') + +LATEX_GRAPHICSPATH = [ + # Allow LaTeX files to access the report assets directory + os.path.join(MEDIA_ROOT, "report", "assets"), +] + # crispy forms use the bootstrap templates CRISPY_TEMPLATE_PACK = 'bootstrap3' diff --git a/InvenTree/config_template.yaml b/InvenTree/config_template.yaml index 64c5db0a06..686f910fbf 100644 --- a/InvenTree/config_template.yaml +++ b/InvenTree/config_template.yaml @@ -73,3 +73,12 @@ log_queries: False sentry: enabled: False # dsn: add-your-sentry-dsn-here + +# LaTeX report rendering +# InvenTree uses the django-tex plugin to enable LaTeX report rendering +# Ref: https://pypi.org/project/django-tex/ +latex: + # Select the LaTeX interpreter to use for PDF rendering + # Note: The intepreter needs to be installed on the system! + # e.g. to install pdflatx: apt-get texlive-latex-base + interpreter: pdflatex diff --git a/InvenTree/report/migrations/0004_auto_20200521_1217.py b/InvenTree/report/migrations/0004_auto_20200521_1217.py new file mode 100644 index 0000000000..c4342ada3d --- /dev/null +++ b/InvenTree/report/migrations/0004_auto_20200521_1217.py @@ -0,0 +1,25 @@ +# Generated by Django 3.0.5 on 2020-05-21 12:17 + +from django.db import migrations, models +import report.models + + +class Migration(migrations.Migration): + + dependencies = [ + ('report', '0003_reportasset'), + ] + + operations = [ + migrations.AddField( + model_name='reporttemplate', + name='filters', + field=models.CharField(blank=True, help_text='Query filters (comma-separated list of key=value pairs)', max_length=250, validators=[report.models.validate_filter_string]), + ), + migrations.AddField( + model_name='reporttemplate', + name='name', + field=models.CharField(default='Test', help_text='Template name', max_length=100, unique=True), + preserve_default=False, + ), + ] diff --git a/InvenTree/report/models.py b/InvenTree/report/models.py index eeebbfbee9..4785f79ab8 100644 --- a/InvenTree/report/models.py +++ b/InvenTree/report/models.py @@ -12,6 +12,8 @@ from django.core.validators import FileExtensionValidator from django.utils.translation import gettext_lazy as _ +from django_tex.shortcuts import render_to_pdf + def rename_template(instance, filename): @@ -28,6 +30,28 @@ class ReportTemplate(models.Model): def __str__(self): return os.path.basename(self.template.name) + @property + def extension(self): + return os.path.splitext(self.template.name)[1].lower() + + def render(self, request, context={}, **kwargs): + """ + Render to template. + """ + + filename = kwargs.get('filename', 'report.pdf') + + template = os.path.join('report_template', os.path.basename(self.template.name)) + + if 1 or self.extension == '.tex': + return render_to_pdf(request, template, context, filename=filename) + + name = models.CharField( + blank=False, max_length=100, + help_text=_('Template name'), + unique=True, + ) + template = models.FileField( upload_to=rename_template, help_text=_("Report template file"), @@ -36,6 +60,13 @@ class ReportTemplate(models.Model): description = models.CharField(max_length=250, help_text=_("Report template description")) + filters = models.CharField( + blank=True, + max_length=250, + help_text=_("Query filters (comma-separated list of key=value pairs)"), + validators=[validate_filter_string] + ) + def rename_asset(instance, filename):