Move the parts for using Word documents as Jinja templates into JinjaService
This commit is contained in:
parent
0db96fbbad
commit
3619240bae
|
@ -12,6 +12,7 @@ from crc.models.file import CONTENT_TYPES, FileModel
|
|||
from crc.models.workflow import WorkflowModel
|
||||
from crc.scripts.script import Script
|
||||
from crc.services.file_service import FileService
|
||||
from crc.services.jinja_service import JinjaService
|
||||
from crc.services.workflow_processor import WorkflowProcessor
|
||||
|
||||
|
||||
|
@ -77,7 +78,7 @@ Takes two arguments:
|
|||
else:
|
||||
image_file_data = None
|
||||
|
||||
return self.make_template(BytesIO(file_data_model.data), task.data, image_file_data)
|
||||
return JinjaService().make_template(BytesIO(file_data_model.data), task.data, image_file_data)
|
||||
|
||||
def get_image_file_data(self, fields_str, task):
|
||||
image_file_data = []
|
||||
|
@ -107,55 +108,3 @@ Takes two arguments:
|
|||
"be a comma-delimited list of File IDs")
|
||||
|
||||
return image_file_data
|
||||
|
||||
def make_template(self, binary_stream, context, image_file_data=None):
|
||||
# TODO: Move this into the jinja_service?
|
||||
doc = DocxTemplate(binary_stream)
|
||||
doc_context = copy.deepcopy(context)
|
||||
doc_context = self.rich_text_update(doc_context)
|
||||
doc_context = self.append_images(doc, doc_context, image_file_data)
|
||||
jinja_env = jinja2.Environment(autoescape=True)
|
||||
try:
|
||||
doc.render(doc_context, jinja_env)
|
||||
except Exception as e:
|
||||
print (e)
|
||||
target_stream = BytesIO()
|
||||
doc.save(target_stream)
|
||||
target_stream.seek(0) # move to the beginning of the stream.
|
||||
return target_stream
|
||||
|
||||
def append_images(self, template, context, image_file_data):
|
||||
context['images'] = {}
|
||||
if image_file_data is not None:
|
||||
for file_data_model in image_file_data:
|
||||
fm = file_data_model.file_model
|
||||
if fm is not None:
|
||||
context['images'][fm.id] = {
|
||||
'name': fm.name,
|
||||
'url': '/v1.0/file/%s/data' % fm.id,
|
||||
'image': self.make_image(file_data_model, template)
|
||||
}
|
||||
|
||||
return context
|
||||
|
||||
def make_image(self, file_data_model, template):
|
||||
return InlineImage(template, BytesIO(file_data_model.data), width=Inches(6.5))
|
||||
|
||||
def rich_text_update(self, context):
|
||||
"""This is a bit of a hack. If we find that /n characters exist in the data, we want
|
||||
these to come out in the final document without requiring someone to predict it in the
|
||||
template. Ideally we would use the 'RichText' feature of the python-docx library, but
|
||||
that requires we both escape it here, and in the Docx template. There is a thing called
|
||||
a 'listing' in python-docx library that only requires we use it on the way in, and the
|
||||
template doesn't have to think about it. So running with that for now."""
|
||||
# loop through the content, identify anything that has a newline character in it, and
|
||||
# wrap that sucker in a 'listing' function.
|
||||
if isinstance(context, dict):
|
||||
for k, v in context.items():
|
||||
context[k] = self.rich_text_update(v)
|
||||
elif isinstance(context, list):
|
||||
for i in range(len(context)):
|
||||
context[i] = self.rich_text_update(context[i])
|
||||
elif isinstance(context, str) and '\n' in context:
|
||||
return Listing(context)
|
||||
return context
|
||||
|
|
|
@ -37,3 +37,58 @@ Cool Right?
|
|||
template = jinja2_env.get_template('main_template')
|
||||
return template.render(**data)
|
||||
|
||||
#
|
||||
# The rest of this is for using Word documents as Jinja templates
|
||||
#
|
||||
def make_template(self, binary_stream, context, image_file_data=None):
|
||||
# TODO: Move this into the jinja_service?
|
||||
doc = DocxTemplate(binary_stream)
|
||||
doc_context = copy.deepcopy(context)
|
||||
doc_context = self.rich_text_update(doc_context)
|
||||
doc_context = self.append_images(doc, doc_context, image_file_data)
|
||||
jinja_env = Environment(autoescape=True)
|
||||
try:
|
||||
doc.render(doc_context, jinja_env)
|
||||
except Exception as e:
|
||||
print (e)
|
||||
target_stream = BytesIO()
|
||||
doc.save(target_stream)
|
||||
target_stream.seek(0) # move to the beginning of the stream.
|
||||
return target_stream
|
||||
|
||||
def rich_text_update(self, context):
|
||||
"""This is a bit of a hack. If we find that /n characters exist in the data, we want
|
||||
these to come out in the final document without requiring someone to predict it in the
|
||||
template. Ideally we would use the 'RichText' feature of the python-docx library, but
|
||||
that requires we both escape it here, and in the Docx template. There is a thing called
|
||||
a 'listing' in python-docx library that only requires we use it on the way in, and the
|
||||
template doesn't have to think about it. So running with that for now."""
|
||||
# loop through the content, identify anything that has a newline character in it, and
|
||||
# wrap that sucker in a 'listing' function.
|
||||
if isinstance(context, dict):
|
||||
for k, v in context.items():
|
||||
context[k] = self.rich_text_update(v)
|
||||
elif isinstance(context, list):
|
||||
for i in range(len(context)):
|
||||
context[i] = self.rich_text_update(context[i])
|
||||
elif isinstance(context, str) and '\n' in context:
|
||||
return Listing(context)
|
||||
return context
|
||||
|
||||
def append_images(self, template, context, image_file_data):
|
||||
context['images'] = {}
|
||||
if image_file_data is not None:
|
||||
for file_data_model in image_file_data:
|
||||
fm = file_data_model.file_model
|
||||
if fm is not None:
|
||||
context['images'][fm.id] = {
|
||||
'name': fm.name,
|
||||
'url': '/v1.0/file/%s/data' % fm.id,
|
||||
'image': self.make_image(file_data_model, template)
|
||||
}
|
||||
|
||||
return context
|
||||
|
||||
@staticmethod
|
||||
def make_image(file_data_model, template):
|
||||
return InlineImage(template, BytesIO(file_data_model.data), width=Inches(6.5))
|
||||
|
|
Loading…
Reference in New Issue