import re import zipfile from pathlib import Path from django.conf import settings from django.test import SimpleTestCase class DocxPaginationTest(SimpleTestCase): def _read_document_xml(self, docx_path: str) -> str: with zipfile.ZipFile(docx_path, "r") as zf: return zf.read("word/document.xml").decode("utf-8", errors="replace") def _extract_pages_text(self, docx_path: str) -> list[str]: """ Extract per-page plain text by walking body elements and splitting on page breaks. Important: we extract w:t texts, so assertions won't be broken by XML tag boundaries. """ import xml.etree.ElementTree as ET xml = self._read_document_xml(docx_path) ns = {"w": "http://schemas.openxmlformats.org/wordprocessingml/2006/main"} root = ET.fromstring(xml) body = root.find("w:body", ns) if body is None: return [] pages: list[list[str]] = [[]] def has_page_break(el) -> bool: for br in el.findall(".//w:br", ns): if br.attrib.get(f"{{{ns['w']}}}type") == "page": return True return False def collect_text(el) -> str: ts = [(t.text or "") for t in el.findall(".//w:t", ns)] return "".join(ts) for child in list(body): text = collect_text(child) if text: pages[-1].append(text) if has_page_break(child): pages.append([]) return ["".join(p) for p in pages if "".join(p).strip()] def test_render_pages_per_page_totals(self): template = str(Path(settings.BASE_DIR) / "print-template.docx") out = str(Path(settings.BASE_DIR) / ".tmp_docx" / "rendered-pages-test.docx") Path(out).parent.mkdir(parents=True, exist_ok=True) from printing.docx_template import render_docx_template_pages prefix = "打印-销售单(8*9)." # Page 1: two non-empty qty cells => 匹数=2, 总数量=111.11 page1 = { f"{prefix}当前页码": "1", f"{prefix}总页数": "2", f"{prefix}匹数": "2", f"{prefix}总数量": "111.11", # Put a couple of quantities too (indices exist 1..72) f"{prefix}销售数量1": "11.11", f"{prefix}销售数量2": "100", # Fill one product line (index 1 exists for product fields) f"{prefix}产品名称1": "P1-产品", f"{prefix}幅宽1": "150cm", f"{prefix}规格1": "规格A", f"{prefix}单位1": "米", } # Page 2: one non-empty qty cell => 匹数=1, 总数量=222.22 page2 = { f"{prefix}当前页码": "2", f"{prefix}总页数": "2", f"{prefix}匹数": "1", f"{prefix}总数量": "222.22", f"{prefix}销售数量1": "222.22", f"{prefix}产品名称1": "P2-产品", f"{prefix}幅宽1": "160cm", f"{prefix}规格1": "规格B", f"{prefix}单位1": "码", } render_docx_template_pages( template_path=template, output_path=out, pages_contexts=[page1, page2], clear_unresolved=True, ) pages_text = self._extract_pages_text(out) self.assertGreaterEqual(len(pages_text), 2, msg="未生成两页文本(可能分页符缺失)") p1, p2 = pages_text[0], pages_text[1] self.assertIn("P1-产品", p1) self.assertIn("111.11", p1) self.assertIn("P2-产品", p2) self.assertIn("222.22", p2) # No raw placeholders should remain (check on plain text concatenation) all_text = "".join(pages_text) self.assertIsNone(re.search(r"#\{.{1,300}?\}", all_text, flags=re.S)) self.assertIsNone(re.search(r"(?