From cd77712b5e83309e9253ec2d885d469da95eaea2 Mon Sep 17 00:00:00 2001 From: ericdufresne Date: Wed, 22 May 2019 15:15:19 -0400 Subject: [PATCH 1/2] Issue #197 - Add support for file-like objects for replace_media --- docxtpl/__init__.py | 27 +++++++++++++++++++-------- tests/header_footer_image_file_obj.py | 23 +++++++++++++++++++++++ 2 files changed, 42 insertions(+), 8 deletions(-) create mode 100644 tests/header_footer_image_file_obj.py diff --git a/docxtpl/__init__.py b/docxtpl/__init__.py index a9b2fd8..192fb56 100644 --- a/docxtpl/__init__.py +++ b/docxtpl/__init__.py @@ -370,10 +370,14 @@ class DocxTemplate(object): return Subdoc(self,docpath) @staticmethod - def get_file_crc(filename): - with open(filename, 'rb') as fh: - buf = fh.read() - crc = (binascii.crc32(buf) & 0xFFFFFFFF) + def get_file_crc(file_obj): + if hasattr(file_obj, 'read'): + buf = file_obj.read() + else: + with open(file_obj, 'rb') as fh: + buf = fh.read() + + crc = (binascii.crc32(buf) & 0xFFFFFFFF) return crc def replace_media(self,src_file,dst_file): @@ -382,17 +386,24 @@ class DocxTemplate(object): This has been done mainly because it is not possible to add images in docx header/footer. With this function, put a dummy picture in your header/footer, - then specify it with its replacement in this function + then specify it with its replacement in this function using the file path + or file-like objects. Syntax: tpl.replace_media('dummy_media_to_replace.png','media_to_paste.jpg') + -- or -- + tpl.replace-media(io.BytesIO(image_stream), io.BytesIO(new_image_stream)) Note: for images, the aspect ratio will be the same as the replaced image Note2 : it is important to have the source media file as it is required to calculate its CRC to find them in the docx """ - with open(dst_file, 'rb') as fh: - crc = self.get_file_crc(src_file) - self.crc_to_new_media[crc] = fh.read() + + crc = self.get_file_crc(src_file) + if hasattr(dst_file, 'read'): + self.crc_to_new_media[crc] = dst_file.read() + else: + with open(dst_file, 'rb') as fh: + self.crc_to_new_media[crc] = fh.read() def replace_pic(self,embedded_file,dst_file): """Replace embedded picture with original-name given by embedded_file. diff --git a/tests/header_footer_image_file_obj.py b/tests/header_footer_image_file_obj.py new file mode 100644 index 0000000..7418efa --- /dev/null +++ b/tests/header_footer_image_file_obj.py @@ -0,0 +1,23 @@ +# -*- coding: utf-8 -*- +''' +Created : 2019-05-22 + +@author: Eric Dufresne +''' + +from docxtpl import DocxTemplate +import io + +DEST_FILE = 'output/header_footer_image_file_obj.docx' + +tpl=DocxTemplate('templates/header_footer_image_tpl.docx') + +context = { + 'mycompany' : 'The World Wide company', +} + +dummy_pic = io.BytesIO(open('templates/dummy_pic_for_header.png', 'rb').read()) +new_image = io.BytesIO(open('templates/python.png', 'rb').read()) +tpl.replace_media(dummy_pic, new_image) +tpl.render(context) +tpl.save(DEST_FILE) \ No newline at end of file From 20819a73685c9d51501e7ea372898777e86444ef Mon Sep 17 00:00:00 2001 From: ericdufresne Date: Wed, 22 May 2019 15:32:48 -0400 Subject: [PATCH 2/2] Fixed doc typo --- docxtpl/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docxtpl/__init__.py b/docxtpl/__init__.py index 192fb56..2458827 100644 --- a/docxtpl/__init__.py +++ b/docxtpl/__init__.py @@ -391,7 +391,7 @@ class DocxTemplate(object): Syntax: tpl.replace_media('dummy_media_to_replace.png','media_to_paste.jpg') -- or -- - tpl.replace-media(io.BytesIO(image_stream), io.BytesIO(new_image_stream)) + tpl.replace_media(io.BytesIO(image_stream), io.BytesIO(new_image_stream)) Note: for images, the aspect ratio will be the same as the replaced image Note2 : it is important to have the source media file as it is required