forked from erp-dev/erp
79 lines
2.7 KiB
Python
79 lines
2.7 KiB
Python
import json
|
||
from pathlib import Path
|
||
|
||
from django.core.management.base import BaseCommand, CommandError
|
||
|
||
|
||
class Command(BaseCommand):
|
||
help = "Render a .docx template by replacing placeholders like #{...} / {...} using a JSON context mapping."
|
||
|
||
def add_arguments(self, parser):
|
||
parser.add_argument(
|
||
"template",
|
||
type=str,
|
||
help="模板文件路径(.docx),例如 /home/f/coding/flower/print-template.docx",
|
||
)
|
||
parser.add_argument(
|
||
"--out",
|
||
type=str,
|
||
default="rendered.docx",
|
||
help="输出 docx 路径(默认 rendered.docx)",
|
||
)
|
||
parser.add_argument(
|
||
"--context-json",
|
||
type=str,
|
||
default="{}",
|
||
help="JSON 字符串,键为占位符内部文本(例如 打印-销售单(8*9).客户名称)",
|
||
)
|
||
parser.add_argument(
|
||
"--context-json-file",
|
||
type=str,
|
||
default=None,
|
||
help="JSON 文件路径(优先级高于 --context-json)",
|
||
)
|
||
parser.add_argument(
|
||
"--keep-unresolved",
|
||
action="store_true",
|
||
help="不清空未命中的占位符(默认会清空)",
|
||
)
|
||
|
||
def handle(self, *args, **options):
|
||
template = str(options["template"])
|
||
out = str(options["out"])
|
||
context_json = str(options["context_json"] or "{}")
|
||
context_json_file = options.get("context_json_file")
|
||
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 context_json_file:
|
||
jp = Path(str(context_json_file))
|
||
if not jp.exists():
|
||
raise CommandError(f"JSON 文件不存在:{context_json_file}")
|
||
context = json.loads(jp.read_text("utf-8"))
|
||
else:
|
||
context = json.loads(context_json)
|
||
|
||
if not isinstance(context, dict):
|
||
raise CommandError("context 必须是 JSON object(字典)")
|
||
|
||
from printing.docx_template import render_docx_template
|
||
|
||
stats = render_docx_template(
|
||
template_path=str(tp),
|
||
output_path=str(out),
|
||
context=context,
|
||
clear_unresolved=(not keep_unresolved),
|
||
)
|
||
|
||
self.stdout.write(
|
||
self.style.SUCCESS(
|
||
f"渲染完成:out={out} paragraphs_touched={stats.paragraphs_touched} placeholders={stats.placeholders_replaced_or_cleared}"
|
||
)
|
||
)
|
||
|