Also look for title and description when replacing pictures
Before, the only searched picture tag was 'name', which corresponds to the file name of the image added to the docx. Also searching in title and description tags makes creating docx templates to be rendered by this more flexible and easier in document editors which do not support viewing the image's original filename, such as Google Docs. Also, picture replacement was comprised of picture map creation and picture replacing. Both processes were merged in order to implement the above change more easily.
This commit is contained in:
parent
d90087d6f7
commit
63cd4c31f7
@ -569,32 +569,33 @@ class DocxTemplate(object):
|
|||||||
def pre_processing(self):
|
def pre_processing(self):
|
||||||
|
|
||||||
if self.pics_to_replace:
|
if self.pics_to_replace:
|
||||||
self.build_pic_map()
|
self._replace_pics()
|
||||||
|
|
||||||
# Do the actual replacement
|
def _replace_pics(self):
|
||||||
for embedded_file, stream in six.iteritems(self.pics_to_replace):
|
"""Replaces pictures xml tags in the docx template with pictures provided by the user"""
|
||||||
if embedded_file not in self.pic_map:
|
|
||||||
raise ValueError('Picture "%s" not found in the docx template'
|
|
||||||
% embedded_file)
|
|
||||||
self.pic_map[embedded_file][1]._blob = stream
|
|
||||||
|
|
||||||
def build_pic_map(self):
|
replaced_pics = {key: False for key in self.pics_to_replace}
|
||||||
"""Searches in docx template all the xml pictures tag and store them
|
|
||||||
in pic_map dict"""
|
|
||||||
if self.pics_to_replace:
|
|
||||||
# Main document
|
|
||||||
part = self.docx.part
|
|
||||||
self.pic_map.update(self._img_filename_to_part(part))
|
|
||||||
|
|
||||||
# Header/Footer
|
# Main document
|
||||||
for relid, rel in six.iteritems(self.docx.part.rels):
|
part = self.docx.part
|
||||||
if rel.reltype in (REL_TYPE.HEADER, REL_TYPE.FOOTER):
|
self._replace_docx_part_pics(part, replaced_pics)
|
||||||
self.pic_map.update(self._img_filename_to_part(rel.target_part))
|
|
||||||
|
# Header/Footer
|
||||||
|
for relid, rel in six.iteritems(part.rels):
|
||||||
|
if rel.reltype in (REL_TYPE.HEADER, REL_TYPE.FOOTER):
|
||||||
|
self._replace_docx_part_pics(rel.target_part, replaced_pics)
|
||||||
|
|
||||||
|
# make sure all template images defined by user were replaced
|
||||||
|
for img_id, replaced in replaced_pics.items():
|
||||||
|
if not replaced:
|
||||||
|
raise ValueError(
|
||||||
|
"Picture %s not found in the docx template" % img_id
|
||||||
|
)
|
||||||
|
|
||||||
def get_pic_map(self):
|
def get_pic_map(self):
|
||||||
return self.pic_map
|
return self.pic_map
|
||||||
|
|
||||||
def _img_filename_to_part(self, doc_part):
|
def _replace_docx_part_pics(self, doc_part, replaced_pics):
|
||||||
|
|
||||||
et = etree.fromstring(doc_part.blob)
|
et = etree.fromstring(doc_part.blob)
|
||||||
|
|
||||||
@ -617,17 +618,37 @@ class DocxTemplate(object):
|
|||||||
else:
|
else:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# title=inl.xpath('wp:docPr/@title',namespaces=docx.oxml.ns.nsmap)[0]
|
non_visual_properties = 'pic:pic/pic:nvPicPr/pic:cNvPr/'
|
||||||
name = gd.xpath('pic:pic/pic:nvPicPr/pic:cNvPr/@name',
|
filename = gd.xpath('%s@name' % non_visual_properties,
|
||||||
namespaces=docx.oxml.ns.nsmap)[0]
|
namespaces=docx.oxml.ns.nsmap)[0]
|
||||||
|
titles = gd.xpath('%s@title' % non_visual_properties,
|
||||||
|
namespaces=docx.oxml.ns.nsmap)
|
||||||
|
if titles:
|
||||||
|
title = titles[0]
|
||||||
|
else:
|
||||||
|
title = ""
|
||||||
|
descriptions = gd.xpath('%s@descr' % non_visual_properties,
|
||||||
|
namespaces=docx.oxml.ns.nsmap)
|
||||||
|
if descriptions:
|
||||||
|
description = descriptions[0]
|
||||||
|
else:
|
||||||
|
description = ""
|
||||||
|
|
||||||
|
part_map[filename] = (doc_part.rels[rel].target_ref,
|
||||||
|
doc_part.rels[rel].target_part)
|
||||||
|
|
||||||
|
# replace data
|
||||||
|
for img_id, img_data in six.iteritems(self.pics_to_replace):
|
||||||
|
if img_id == filename or img_id == title or img_id == description:
|
||||||
|
part_map[filename][1]._blob = img_data
|
||||||
|
replaced_pics[img_id] = True
|
||||||
|
break
|
||||||
|
|
||||||
part_map[name] = (doc_part.rels[rel].target_ref,
|
|
||||||
doc_part.rels[rel].target_part)
|
|
||||||
# FIXME: figure out what exceptions are thrown here and catch more specific exceptions
|
# FIXME: figure out what exceptions are thrown here and catch more specific exceptions
|
||||||
except Exception:
|
except Exception:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
return part_map
|
self.pic_map.update(part_map)
|
||||||
|
|
||||||
def build_url_id(self, url):
|
def build_url_id(self, url):
|
||||||
return self.docx._part.relate_to(url, REL_TYPE.HYPERLINK,
|
return self.docx._part.relate_to(url, REL_TYPE.HYPERLINK,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user