from pathlib import Path from django.conf import settings from django.core.management.base import BaseCommand, CommandError class Command(BaseCommand): help = "Render a .docx template with realistic mock data (no database required)." def add_arguments(self, parser): parser.add_argument( "--template", type=str, default=str(Path(settings.BASE_DIR) / "print-template.docx"), help="docx 模板路径(默认 BASE_DIR/print-template.docx)", ) parser.add_argument( "--out", type=str, default="", help="输出 docx 路径(默认 .tmp_docx/mock-rendered.docx)", ) parser.add_argument( "--seed", type=int, default=20260126, help="随机种子(默认 20260126),便于复现同一份拟真数据", ) parser.add_argument( "--pages", type=int, default=1, help="生成页数(每页固定 9 行明细),默认 1", ) parser.add_argument( "--printer", type=str, default="系统自动生成", help="填充 {打印人}", ) parser.add_argument( "--keep-unresolved", action="store_true", help="不清空未命中的占位符(默认会清空)", ) def handle(self, *args, **options): template = str(options.get("template") or "") out = str(options.get("out") or "") seed = int(options.get("seed") or 0) pages = int(options.get("pages") or 1) printer = str(options.get("printer") or "") keep_unresolved = bool(options.get("keep_unresolved")) tp = Path(template) if not tp.exists(): raise CommandError(f"模板文件不存在:{template}") if tp.suffix.lower() != ".docx": raise CommandError("template 必须是 .docx 文件") if not out: out = str(Path(settings.BASE_DIR) / ".tmp_docx" / "mock-rendered.docx") Path(out).parent.mkdir(parents=True, exist_ok=True) from printing.docx_template import extract_docx_placeholders, render_docx_template_pages from printing.print_docx_services import build_debug_context_summary, build_mock_sales_docx_pages placeholders = extract_docx_placeholders(template_path=str(tp)) page_contexts = build_mock_sales_docx_pages( placeholders=placeholders, pages=pages, printer_label=printer, seed=seed, ) # stats: aggregate all page contexts ctx_stats = build_debug_context_summary({k: v for d in page_contexts for k, v in d.items()}) stats = render_docx_template_pages( template_path=str(tp), output_path=str(out), pages_contexts=page_contexts, clear_unresolved=(not keep_unresolved), ) self.stdout.write( self.style.SUCCESS( "渲染完成:" f" out={out}" f" seed={seed}" f" pages={pages}" f" paragraphs_touched={stats.paragraphs_touched}" f" placeholders_replaced_or_cleared={stats.placeholders_replaced_or_cleared}" f" context_filled={ctx_stats['context_filled_keys']}/{ctx_stats['context_total_keys']}" ) )