Skip to content

Instantly share code, notes, and snippets.

@dpwiz
Last active August 7, 2017 18:50
Show Gist options
  • Save dpwiz/5168693 to your computer and use it in GitHub Desktop.
Save dpwiz/5168693 to your computer and use it in GitHub Desktop.
Render LaTeX code generated with Django templates to a PDF response.
\documentclass[a4paper]{article}
% Cyrillic support
\usepackage[T2A]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage[english,russian]{babel}
\DeclareSymbolFont{T2Aletters}{T2A}{cmr}{m}{it}
% PDF search & cut'n'paste
\usepackage{cmap}
% Page options
\usepackage{geometry}
\geometry{left=1cm}
\geometry{right=1cm}
\geometry{top=1cm}
\geometry{bottom=1.25cm}
% Misc options
\setcounter{secnumdepth}{5}
\usepackage[parfill]{parskip}
\nonstopmode
{% block extraheader %}{% endblock %}
\title{% templatetag openbrace %}{% block title %}{% endblock %}}
\author{% templatetag openbrace %}{% block author %}{% endblock %}}
\date{% templatetag openbrace %}{% block date %}{% endblock %}}
\begin{document}
{% block document %}{% endblock %}
\end{document}
from django.template.loader import get_template
from django.template import TemplateDoesNotExist, Context
from django.http import HttpResponse, Http404, HttpResponseNotModified
from django.core.cache import cache
from django.conf import settings
from tempfile import mkdtemp
import subprocess
import os
import shutil
from hashlib import md5
TEMP_PREFIX = getattr(settings, 'TEX_TEMP_PREFIX', 'render_tex-')
CACHE_PREFIX = getattr(settings, 'TEX_CACHE_PREFIX', 'render-tex')
CACHE_TIMEOUT = getattr(settings, 'TEX_CACHE_TIMEOUT', 86400) # 1 day
def render_tex(request, template, ctx={}):
doc = template.rsplit('/', 1)[-1].rsplit('.', 1)[0]
try:
body = get_template(template).render(Context(ctx)).encode("utf-8")
except TemplateDoesNotExist:
raise Http404()
etag = md5(body).hexdigest()
if request.META.get('HTTP_IF_NONE_MATCH', '') == etag:
return HttpResponseNotModified()
cache_key = "%s:%s:%s" % (CACHE_PREFIX, template, etag)
pdf = cache.get(cache_key)
if pdf is None:
if '\\nonstopmode' not in body:
raise ValueError("\\nonstopmode not present in document, cowardly refusing to process.")
tmp = mkdtemp(prefix=TEMP_PREFIX)
try:
with open("%s/%s.tex" % (tmp, doc), "w") as f:
f.write(body)
del body
error = subprocess.Popen(
["pdflatex", "%s.tex" % doc],
cwd=tmp,
stdin=open(os.devnull, "r"),
stderr=open(os.devnull, "wb"),
stdout=open(os.devnull, "wb")
).wait()
if error:
if request.user.is_superuser:
log = open("%s/%s.log" % (tmp, doc)).read()
return HttpResponse(log, mimetype="text/plain")
else:
raise RuntimeError("pdflatex error (code %s) in %s/%s" % (error, tmp, doc))
pdf = open("%s/%s.pdf" % (tmp, doc))
finally:
shutil.rmtree(tmp)
if pdf:
cache.set(cache_key, pdf, CACHE_TIMEOUT)
res = HttpResponse(pdf, mimetype="application/pdf")
res['ETag'] = etag
return res
@wlwzrd
Copy link

wlwzrd commented Feb 6, 2015

Hi, I'm trying to put some pics on the latex doc, but I don't know where I can put the images.
Actually I have something like this:
myapp
----- models.py
----- views.py
----- urls.py
-----TEMPLATES/
----------base.tex
---------- image1.png

So I'm using {graphicx} like this \includegraphics{image1} but this doesn't generate the PDF
please I would like to know how to fix it.

@tuxador
Copy link

tuxador commented Mar 2, 2016

heu wlwzrd you should put your images in a static folder and define this folder in your settings.py

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment