mirror of
https://github.com/nanoy42/coope
synced 2024-12-23 23:43:47 +00:00
Latex
This commit is contained in:
parent
b5a1df1271
commit
63e076de5f
13 changed files with 6 additions and 189 deletions
|
@ -39,7 +39,7 @@ INSTALLED_APPS = [
|
||||||
'dal_select2',
|
'dal_select2',
|
||||||
'simple_history',
|
'simple_history',
|
||||||
'django_tex',
|
'django_tex',
|
||||||
'debug_toolbar'
|
'debug_toolbar',
|
||||||
]
|
]
|
||||||
|
|
||||||
MIDDLEWARE = [
|
MIDDLEWARE = [
|
||||||
|
@ -133,4 +133,3 @@ MEDIA_URL = '/media/'
|
||||||
INTERNAL_IPS = ["127.0.0.1"]
|
INTERNAL_IPS = ["127.0.0.1"]
|
||||||
|
|
||||||
EMAIL_SUBJECT_PREFIX = "[Coopé Technopôle Metz] "
|
EMAIL_SUBJECT_PREFIX = "[Coopé Technopôle Metz] "
|
||||||
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend' # During development only
|
|
|
@ -1,21 +0,0 @@
|
||||||
MIT License
|
|
||||||
|
|
||||||
Copyright (c) 2017 Martin Bierbaum
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
|
||||||
copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
|
@ -1,50 +0,0 @@
|
||||||
|
|
||||||
import os
|
|
||||||
from subprocess import PIPE, run
|
|
||||||
import tempfile
|
|
||||||
|
|
||||||
from django.template.loader import get_template
|
|
||||||
|
|
||||||
from django_tex.exceptions import TexError
|
|
||||||
from django.conf import settings
|
|
||||||
|
|
||||||
DEFAULT_INTERPRETER = 'pdflatex'
|
|
||||||
|
|
||||||
def run_tex(source):
|
|
||||||
"""
|
|
||||||
Copy the source to temp dict and run latex.
|
|
||||||
"""
|
|
||||||
with tempfile.TemporaryDirectory() as tempdir:
|
|
||||||
filename = os.path.join(tempdir, 'texput.tex')
|
|
||||||
with open(filename, 'x', encoding='utf-8') as f:
|
|
||||||
f.write(source)
|
|
||||||
print(source)
|
|
||||||
latex_interpreter = getattr(settings, 'LATEX_INTERPRETER', DEFAULT_INTERPRETER)
|
|
||||||
latex_command = 'cd "{tempdir}" && {latex_interpreter} -interaction=batchmode {path}'.format(tempdir=tempdir, latex_interpreter=latex_interpreter, path=os.path.basename(filename))
|
|
||||||
process = run(latex_command, shell=True, stdout=PIPE, stderr=PIPE)
|
|
||||||
try:
|
|
||||||
if process.returncode == 1:
|
|
||||||
with open(os.path.join(tempdir, 'texput.log'), encoding='utf8') as f:
|
|
||||||
log = f.read()
|
|
||||||
raise TexError(log=log, source=source)
|
|
||||||
with open(os.path.join(tempdir, 'texput.pdf'), 'rb') as pdf_file:
|
|
||||||
pdf = pdf_file.read()
|
|
||||||
except FileNotFoundError:
|
|
||||||
if process.stderr:
|
|
||||||
raise Exception(process.stderr.decode('utf-8'))
|
|
||||||
raise
|
|
||||||
return pdf
|
|
||||||
|
|
||||||
def compile_template_to_pdf(template_name, context):
|
|
||||||
"""
|
|
||||||
Compile the source with :func:`~django_tex.core.render_template_with_context` and :func:`~django_tex.core.run_tex`.
|
|
||||||
"""
|
|
||||||
source = render_template_with_context(template_name, context)
|
|
||||||
return run_tex(source)
|
|
||||||
|
|
||||||
def render_template_with_context(template_name, context):
|
|
||||||
"""
|
|
||||||
Render the template
|
|
||||||
"""
|
|
||||||
template = get_template(template_name, using='tex')
|
|
||||||
return template.render(context)
|
|
|
@ -1,11 +0,0 @@
|
||||||
|
|
||||||
from django.template.backends.jinja2 import Jinja2
|
|
||||||
|
|
||||||
class TeXEngine(Jinja2):
|
|
||||||
app_dirname = 'templates'
|
|
||||||
|
|
||||||
def __init__(self, params):
|
|
||||||
default_environment = 'django_tex.environment.environment'
|
|
||||||
if 'environment' not in params['OPTIONS'] or not params['OPTIONS']['environment']:
|
|
||||||
params['OPTIONS']['environment'] = default_environment
|
|
||||||
super().__init__(params)
|
|
|
@ -1,16 +0,0 @@
|
||||||
|
|
||||||
from jinja2 import Environment
|
|
||||||
|
|
||||||
from django.template.defaultfilters import register
|
|
||||||
|
|
||||||
from django_tex.filters import FILTERS as tex_specific_filters
|
|
||||||
|
|
||||||
# Django's built-in filters ...
|
|
||||||
filters = register.filters
|
|
||||||
# ... updated with tex specific filters
|
|
||||||
filters.update(tex_specific_filters)
|
|
||||||
|
|
||||||
def environment(**options):
|
|
||||||
env = Environment(**options)
|
|
||||||
env.filters = filters
|
|
||||||
return env
|
|
|
@ -1,40 +0,0 @@
|
||||||
|
|
||||||
import re
|
|
||||||
|
|
||||||
def prettify_message(message):
|
|
||||||
'''
|
|
||||||
Helper methods that removes consecutive whitespaces and newline characters
|
|
||||||
'''
|
|
||||||
# Replace consecutive whitespaces with a single whitespace
|
|
||||||
message = re.sub(r'[ ]{2,}', ' ', message)
|
|
||||||
# Replace consecutive newline characters, optionally separated by whitespace, with a single newline
|
|
||||||
message = re.sub(r'([\r\n][ \t]*)+', '\n', message)
|
|
||||||
return message
|
|
||||||
|
|
||||||
def tokenizer(code):
|
|
||||||
token_specification = [
|
|
||||||
('ERROR', r'\! (?:.+[\r\n])+[\r\n]+'),
|
|
||||||
('WARNING', r'latex warning.*'),
|
|
||||||
('NOFILE', r'no file.*')
|
|
||||||
]
|
|
||||||
token_regex = '|'.join('(?P<{}>{})'.format(label, regex) for label, regex in token_specification)
|
|
||||||
for m in re.finditer(token_regex, code, re.IGNORECASE):
|
|
||||||
token_dict = dict(type=m.lastgroup, message=prettify_message(m.group()))
|
|
||||||
yield token_dict
|
|
||||||
|
|
||||||
class TexError(Exception):
|
|
||||||
|
|
||||||
def __init__(self, log, source):
|
|
||||||
self.log = log
|
|
||||||
self.source = source
|
|
||||||
self.tokens = list(tokenizer(self.log))
|
|
||||||
self.message = self.get_message()
|
|
||||||
|
|
||||||
def get_message(self):
|
|
||||||
for token in self.tokens:
|
|
||||||
if token['type'] == 'ERROR':
|
|
||||||
return token['message']
|
|
||||||
return 'No error message found in log'
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return self.message
|
|
|
@ -1,9 +0,0 @@
|
||||||
from django.utils.formats import localize_input
|
|
||||||
|
|
||||||
def do_linebreaks(value):
|
|
||||||
return value.replace('\n', '\\\\\n')
|
|
||||||
|
|
||||||
FILTERS = {
|
|
||||||
'localize': localize_input,
|
|
||||||
'linebreaks': do_linebreaks
|
|
||||||
}
|
|
|
@ -1,19 +0,0 @@
|
||||||
from django.db import models
|
|
||||||
from django.core.exceptions import ValidationError
|
|
||||||
from django.template import TemplateDoesNotExist
|
|
||||||
from django.utils.translation import ugettext_lazy as _
|
|
||||||
from django.template.loader import get_template
|
|
||||||
|
|
||||||
def validate_template_path(name):
|
|
||||||
try:
|
|
||||||
get_template(name, using='tex')
|
|
||||||
except TemplateDoesNotExist:
|
|
||||||
raise ValidationError(_('Template not found.'))
|
|
||||||
|
|
||||||
class TeXTemplateFile(models.Model):
|
|
||||||
|
|
||||||
title = models.CharField(max_length=255)
|
|
||||||
name = models.CharField(max_length=255, validators=[validate_template_path,])
|
|
||||||
|
|
||||||
class Meta:
|
|
||||||
abstract = True
|
|
|
@ -1,17 +0,0 @@
|
||||||
|
|
||||||
from django.http import HttpResponse
|
|
||||||
|
|
||||||
from django_tex.core import compile_template_to_pdf
|
|
||||||
|
|
||||||
class PDFResponse(HttpResponse):
|
|
||||||
|
|
||||||
def __init__(self, content, filename=None):
|
|
||||||
super(PDFResponse, self).__init__(content_type='application/pdf')
|
|
||||||
self['Content-Disposition'] = 'filename="{}"'.format(filename)
|
|
||||||
self.write(content)
|
|
||||||
|
|
||||||
|
|
||||||
def render_to_pdf(request, template_name, context=None, filename=None):
|
|
||||||
# Request is not needed and only included to make the signature conform to django's render function
|
|
||||||
pdf = compile_template_to_pdf(template_name, context)
|
|
||||||
return PDFResponse(pdf, filename=filename)
|
|
|
@ -88,9 +88,9 @@ Facture FE\FactureNum
|
||||||
À régler par chèque, espèces ou par virement bancaire :
|
À régler par chèque, espèces ou par virement bancaire :
|
||||||
\begin{center}
|
\begin{center}
|
||||||
\begin{tabular}{|c c c c|}
|
\begin{tabular}{|c c c c|}
|
||||||
\hline \textbf{Code banque} & \textbf{Code guichet}& \textbf{Nº de Compte} & \textbf{Clé RIB} \\
|
\hline \textbf{Code banque} & \textbf{Code guichet}& \textbf{N$^\circ{}$ de Compte} & \textbf{Clé RIB} \\
|
||||||
20041 & 01010 & 1074350Z031 & 48 \\
|
20041 & 01010 & 1074350Z031 & 48 \\
|
||||||
\hline \textbf{IBAN Nº} & \multicolumn{3}{|l|}{ FR82 2004 1010 1010 7435 0Z03 148 } \\
|
\hline \textbf{IBAN N$^\circ{}$} & \multicolumn{3}{|l|}{ FR82 2004 1010 1010 7435 0Z03 148 } \\
|
||||||
\hline \textbf{BIC} & \multicolumn{3}{|l|}{ PSSTFRPPNCY }\\
|
\hline \textbf{BIC} & \multicolumn{3}{|l|}{ PSSTFRPPNCY }\\
|
||||||
\hline \textbf{Domiciliation} & \multicolumn{3}{|l|}{La Banque Postale - Centre Financier - 54900 Nancy CEDEX 9}\\
|
\hline \textbf{Domiciliation} & \multicolumn{3}{|l|}{La Banque Postale - Centre Financier - 54900 Nancy CEDEX 9}\\
|
||||||
\hline \textbf{Titulaire} & \multicolumn{3}{|l|}{ASSO COOPE TECHNOPOLE METZ}\\
|
\hline \textbf{Titulaire} & \multicolumn{3}{|l|}{ASSO COOPE TECHNOPOLE METZ}\\
|
||||||
|
|
|
@ -6,3 +6,4 @@ docutils==0.14
|
||||||
django-simple-history==2.5.1
|
django-simple-history==2.5.1
|
||||||
jinja2==2.10
|
jinja2==2.10
|
||||||
Sphinx==1.8.4
|
Sphinx==1.8.4
|
||||||
|
django-tex==1.1.7
|
||||||
|
|
|
@ -358,7 +358,7 @@ def gen_user_infos(request, pk):
|
||||||
"""
|
"""
|
||||||
Generates a latex document include adhesion certificate and list of `cotisations <users.models.CotisationHistory>`.
|
Generates a latex document include adhesion certificate and list of `cotisations <users.models.CotisationHistory>`.
|
||||||
"""
|
"""
|
||||||
user= get_object_or_404(User, pk=pk)
|
user = get_object_or_404(User, pk=pk)
|
||||||
cotisations = CotisationHistory.objects.filter(user=user).order_by('-paymentDate')
|
cotisations = CotisationHistory.objects.filter(user=user).order_by('-paymentDate')
|
||||||
now = datetime.now()
|
now = datetime.now()
|
||||||
path = os.path.join(settings.BASE_DIR, "templates/coope.png")
|
path = os.path.join(settings.BASE_DIR, "templates/coope.png")
|
||||||
|
|
Loading…
Reference in a new issue