Skip to content

Commit 76e1d21

Browse files
authored
Merge pull request #42 from DataManagementLab/6_Export_Basic_pdf_export_for_own_coursebook
export: basic pdf export for own coursebook
2 parents 08f8770 + f16918e commit 76e1d21

11 files changed

Lines changed: 195 additions & 2 deletions

File tree

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{% load cc_export_tags %}
2+
{% autoescape off %}
3+
4+
\textbf{Image}
5+
\Image{ {{content.description|tex_escape}} }{% templatetag openbrace %}{{content.imagecontent.image.path}}{% templatetag closebrace%}
6+
\newline
7+
{{content.description|tex_escape}}
8+
\newline
9+
10+
{% endautoescape %}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{% load cc_export_tags %}
2+
{% autoescape off %}
3+
\textbf{YouTube video}
4+
\newline
5+
\href{ {{ content.ytvideocontent.url }} }{ {{ content.ytvideocontent.url }} }
6+
\newline
7+
{{content.description|tex_escape}}
8+
\newline
9+
{% endautoescape %}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
{% load cc_export_tags %}
2+
{% autoescape off %}
3+
4+
\documentclass[a4paper]{article}
5+
6+
\usepackage[utf8]{inputenc}
7+
\usepackage[T1]{fontenc}
8+
\usepackage[ngerman]{babel}
9+
\usepackage{graphicx}
10+
\usepackage{float}
11+
\usepackage{grffile}
12+
\usepackage{hyperref}
13+
\usepackage[left=1cm, right=1cm, top=2cm, bottom=2cm]{geometry}
14+
15+
%% Generate a latex graphic
16+
% 1: caption
17+
% 2: image path
18+
\newcommand{\Image}[2]{
19+
\begin{figure}[H]
20+
\centering
21+
\includegraphics[width=\textwidth]{#2}
22+
\caption{#1}
23+
\end{figure}
24+
}
25+
26+
\begin{document}
27+
28+
\title{ {{ course.title|tex_escape }} }
29+
\author{ {{user|tex_escape}} }
30+
\maketitle
31+
32+
% \end{document} gets appended in code
33+
34+
{% endautoescape %}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
\textit{This content type is not supported at the moment.}

export/helper_functions.py

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import os
2+
import shutil
3+
import tempfile
4+
from subprocess import Popen, PIPE
5+
6+
from django.template.loader import get_template
7+
8+
from export.templatetags.cc_export_tags import export_template
9+
10+
11+
class LaTeX:
12+
13+
encoding = 'utf-8'
14+
15+
@staticmethod
16+
def render(context, template_name, assets, app='export', external_assets=None):
17+
"""
18+
https://github.com/d120/pyophase/blob/master/ophasebase/helper.py
19+
Retrieved 10.08.2020
20+
"""
21+
22+
template = get_template(template_name)
23+
rendered_tpl = template.render(context).encode(LaTeX.encoding)
24+
# prerender content templates
25+
for content in context['contents']:
26+
rendered_tpl += LaTeX.pre_render(content)
27+
rendered_tpl += "\end{document}".encode(LaTeX.encoding)
28+
29+
with tempfile.TemporaryDirectory() as tempdir:
30+
# for asset in assets:
31+
# shutil.copy(os.path.dirname(os.path.realpath(__file__)) + '/../' + app + '/assets/' + asset, tempdir)
32+
# if external_assets is not None:
33+
# for asset in external_assets:
34+
# shutil.copy(asset, tempdir)
35+
process = Popen(['pdflatex'], stdin=PIPE, stdout=PIPE, cwd=tempdir, )
36+
pdflatex_output = process.communicate(rendered_tpl)
37+
try:
38+
with open(os.path.join(tempdir, 'texput.pdf'), 'rb') as f:
39+
pdf = f.read()
40+
except FileNotFoundError:
41+
pdf = None
42+
return pdf, pdflatex_output, rendered_tpl
43+
44+
@staticmethod
45+
def pre_render(content):
46+
template = get_template(export_template(content.type))
47+
context = {'content': content}
48+
return template.render(context).encode(LaTeX.encoding)

export/templatetags/__init__.py

Whitespace-only changes.
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import os
2+
import re
3+
4+
from django import template
5+
from django.template.defaultfilters import stringfilter
6+
from content.models import CONTENT_TYPES
7+
import content
8+
9+
register = template.Library()
10+
11+
12+
@register.filter
13+
def export_template(type):
14+
base_path = os.path.dirname(content.__file__)
15+
path = base_path + f"/templates/content/export"
16+
if type in CONTENT_TYPES.keys():
17+
return path + f"/{type}.tex"
18+
return path + "/invalid.tex"
19+
20+
21+
@register.filter
22+
@stringfilter
23+
def tex_escape(value):
24+
"""Escape characters with special meaning in LaTeX.
25+
https://github.com/d120/pyophase/blob/master/ophasebase/templatetags/tex_escape.py
26+
retrieved: 10.08.2020
27+
"""
28+
replacements = {
29+
'&': r'\&',
30+
'%': r'\%',
31+
'$': r'\$',
32+
'#': r'\#',
33+
'_': r'\_',
34+
'{': r'\{',
35+
'}': r'\}',
36+
'~': r'\textasciitilde{}',
37+
'^': r'\^{}',
38+
'\\': r'\textbackslash{}',
39+
'<': r'\textless{}',
40+
'>': r'\textgreater{}',
41+
}
42+
regex = re.compile('|'.join(re.escape(key) for key in replacements))
43+
return regex.sub(lambda match: replacements[match.group()], value)

export/views.py

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,34 @@
1+
from django.http import HttpResponse
12
from django.shortcuts import render
23

3-
# Create your views here.
4+
from base.models import Course, Favorite
5+
from export.helper_functions import LaTeX
6+
7+
8+
def generate_coursebook(request, pk, template="content/export/base.tex", context=None):
9+
""" Generates a PDF file with nametags for students in the queryset"""
10+
if context is None:
11+
context = {}
12+
user = request.user
13+
course = Course.objects.get(pk=pk)
14+
context['user'] = user
15+
context['course'] = course
16+
context['contents'] = [favorite.content for favorite in Favorite.objects.filter(user=user.profile, course=course)]
17+
(pdf, pdflatex_output, tex_template) = LaTeX.render(context, template, [])
18+
return pdf, pdflatex_output, tex_template
19+
20+
21+
def generate_coursebook_response(request, pk, filename='coursebook.pdf'):
22+
""" Generates a PDF file with nametags for students in the queryset and sends it to the browser"""
23+
(pdf, pdflatex_output, tex_template) = generate_coursebook(request, pk)
24+
25+
return write_response(request, pdf, pdflatex_output, tex_template, filename)
26+
27+
28+
def write_response(request, pdf, pdflatex_output, tex_template, filename, content_type='application/pdf'):
29+
if not pdf:
30+
return render(request, "frontend/coursebook/rendering-error.html", {"content": pdflatex_output[0].decode("utf-8"), "tex_template": tex_template.decode("utf-8")})
31+
response = HttpResponse(content_type=content_type)
32+
response['Content-Disposition'] = 'attachment; filename=' + filename
33+
response.write(pdf)
34+
return response

frontend/templates/frontend/course/coursebook.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
<div class="mt-3">
88
{% with user|get_coursebook:course as topic_contents %}
99
{% if topic_contents|length > 0 %}
10-
<a href="" class="btn btn-primary float-right text-right">{% trans 'Export' %}</a>
10+
<a href="{% url 'frontend:coursebook-generate' course.id %}" target="_blank" class="btn btn-primary float-right text-right">{% trans 'Export' %}</a>
1111
{% endif %}
1212
<button class="btn btn-primary float-left mr-1" type="button" data-toggle="collapse" data-target="#collapseCoursebook"
1313
aria-expanded="false" aria-controls="collapseCoursebook">
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
{% extends 'frontend/base_logged_in.html' %}
2+
3+
{# Load the tag library #}
4+
{% load bootstrap4 %}
5+
{% load i18n %}
6+
7+
{% block title %}Error - Collab Coursebook{% endblock %}
8+
9+
{% block content %}
10+
<h1>Error</h1>
11+
<p>An error occured while generating your coursebook. Please see the log file below.</p>
12+
<p>{{ content|linebreaks}}</p>
13+
<h3>Latex Template</h3>
14+
<p>{{ tex_template|linebreaksbr }}</p>
15+
{% endblock %}

0 commit comments

Comments
 (0)