InvenTree Label Sheet 插件实战:单张标签纸网格排版 PDF 打印指南

发布时间:2026/9/16 17:30:02
InvenTree Label Sheet 插件实战:单张标签纸网格排版 PDF 打印指南 InvenTree Label Sheet 插件实战单张标签纸网格排版 PDF 打印指南【免费下载链接】InvenTreeOpen Source Inventory Management System项目地址: https://gitcode.com/GitHub_Trending/in/InvenTree本篇指南围绕 InvenTree 内置的InvenTree Label Sheet PluginInvenTreeLabelSheet展开讲解如何将多枚标签按规则网格自动排列到单张标准标签纸上并生成 PDF。读完本文你将掌握该插件的启用机制、五个打印选项页面大小、跳过标签、边框、横向、页边距的实际含义与取值约束、DEBUG 模式的使用场景以及从标签模板到网格排版再到 PDF 渲染的完整实现链路。插件概览什么是 Label Sheet 插件InvenTree Label Sheet Plugin是 InvenTree 提供的内置标签打印插件核心功能是把多枚标签合并到一张更大的纸张上按规则网格regular grid排布最终输出一个 PDF 文件。这一能力在以下场景中非常实用使用 A4、Letter 等标准整页标签纸如预切 21×10 或 24×8 的空白标签纸时把一批零件、库存项StockItem的标签一次性铺满整张纸需要按 3 列 × 8 行这类固定网格打印标签时避免一枚标签一页造成的纸张浪费需要跳过部分标签位置例如标签纸首行已被手工占用时进行偏移打印。该插件通过 LabelPrintingMixin 标签打印混入类 提供自定义打印支持是 InvenTree 标签打印插件体系中合并多标签到单页这一典型用法的内置实现。从源码结构看插件由 label_sheet.py 实现位于plugin/builtin/labels/目录下与默认 PDF 标签插件 inventree_label.pyInvenTreeLabel、机器标签插件 inventree_machine.py 并列。启用机制强制启用的内置插件Label Sheet 插件是一个强制mandatory插件始终处于启用状态无需手动安装或激活。在源码中这一特性体现为类声明class InvenTreeLabelSheetPlugin(LabelPrintingMixin, SettingsMixin, InvenTreePlugin)插件元数据NAME InvenTreeLabelSheet、TITLE InvenTree Label Sheet Printer、DESCRIPTION Arrays multiple labels onto a single sheet、VERSION 1.0.1关键行为标记BLOCKING_PRINT True表示打印任务会同步阻塞前端服务器直至完成不会卸载到后台 worker保证 PDF 立即可下载。因此你不需要任何安装步骤只要 InvenTree 正常运行该插件就会出现在可选的标签打印插件列表中。插件设置DEBUG 调试模式插件通过SettingsMixin暴露了一个插件级设置项DEBUGSETTINGS { DEBUG: { name: _(Debug mode), description: _(Enable debug mode - returns raw HTML instead of PDF), validator: bool, default: False, } }设置键名称默认值说明DEBUGDebug modeFalse开启后插件返回原始 HTMLlabels.html而非 PDF该模式仅供开发和测试使用不应在生产环境中启用开启后打印任务返回的是未经 PDF 渲染的原始 HTML 文档见下节源码中str2bool(self.get_setting(DEBUG))分支由于跳过 WeasyPrint 渲染可能无法生成有效的 PDF 文件不能用于实际标签打印典型用途排查标签模板的渲染错误例如检查模板变量未解析、CSS 未生效等模板层问题。在 InvenTree 后台的插件设置界面中该项显示为开关形式的 Debug mode 字段其描述文字为 Enable debug mode - returns raw HTML instead of PDF。使用方式在打印对话框中选用插件打印标签时从插件列表中选择InvenTreeLabelSheet选项插件便会将所选对象的标签排版到单张纸上并生成包含全部标签的 PDF 文件供下载。打印对话框为本次打印任务提供了一组额外的自定义选项由插件内部的LabelPrintingOptionsSerializer定义。五个打印选项详解选项字段类型默认值取值范围/约束说明page_sizeChoiceFieldA4A4/A3/Legal/Letter标签页的纸张规格skipIntegerField0最小 0最大 500打印标签页时跳过的标签数量用于位置偏移borderBooleanFieldFalseTrue/False是否为每枚标签打印 1px 黑色边框便于裁剪定位landscapeBooleanFieldFalseTrue/False是否以横向模式打印标签页宽高互换marginIntegerField10最小 0单位 mm页面四周的页边距单位为毫米各选项在打印对话框中的含义与界面截图一致顶部为模板Template与打印插件Printing Plugin选择下方依次是Page Size页面大小默认 A4、Skip Labels跳过标签默认 0、Border边框默认关闭、Landscape横向默认关闭底部为 Cancel / Print 按钮。page_size的可选值来自 report.helpers.report_page_size_options()与报表系统共用同一套页面规格定义其实际尺寸单位 mm由 report.helpers.page_sizes() 给出页面代码尺寸mmA4210 × 297A3297 × 420Legal215.9 × 355.6Letter215.9 × 279.4若传入未知的页面代码page_size()会记录警告并默认回退到 A4见 report/helpers.py。打印选项在任务中的传递这些选项在print_labels方法中通过kwargs[printing_options]读取序列化器被赋给类属性PrintingOptionsSerializer LabelPrintingOptionsSerializer由 LabelPrintingMixin 机制注入打印界面并随任务下发printing_options kwargs[printing_options] page_size_code printing_options.get(page_size, A4) landscape printing_options.get(landscape, False) border printing_options.get(border, False) skip int(printing_options.get(skip, 0)) margin printing_options.get(margin, 10)实现原理从网格计算到 PDF 渲染InvenTreeLabelSheetPlugin对 LabelPrintingMixin 的入口方法print_labels进行了整体重写源码注释明确说明 we override the entire print_labels method以完成网格排版。整个过程可分为四个阶段。阶段一计算可用空间与网格行列数# 获取页面尺寸mm page_size report.helpers.page_size(page_size_code) page_width, page_height page_size # 横向模式交换宽高 if landscape: page_width, page_height page_height, page_width # 扣除页边距后的可用空间 available_width page_width - (2 * margin) available_height page_height - (2 * margin) # 按标签实际尺寸计算行列数向下取整 n_cols math.floor(available_width / label.width) n_rows math.floor(available_height / label.height) n_cells n_cols * n_rows if n_cells 0: raise ValidationError(_(Label is too large for page size))要点网格行列数完全由标签模板的width/heightmm与扣除边距后的页面尺寸决定因此不必手动配置每页多少枚标签当标签尺寸大于页面可用空间时n_cells 0插件会抛出ValidationError提示 Label is too large for page size从源码结构可以推断调整margin或切换landscape会直接改变可用空间进而影响单页标签数量。阶段二跳过标签与分页切片# 在标签列表前插入 skip 个空占位 items [None] * skip list(items) n_labels len(items) # 文档级数据 document_data { border: border, landscape: landscape, page_width: page_width, page_height: page_height, label_width: label.width, label_height: label.height, n_labels: n_labels, n_pages: math.ceil(n_labels / n_cells), n_cols: n_cols, n_rows: n_rows, margin: margin, }随后按每页n_cells枚进行切片并逐页渲染同时更新打印进度while idx n_labels: if page : self.print_page(label, items[idx : idx n_cells], request, **document_data): pages.append(page) idx n_cells output.progress 1 output.save()若最终没有任何页面生成例如所有标签渲染失败则抛出ValidationError(No labels were generated)。阶段三单页网格渲染print_page方法把一页内的标签渲染成一张 HTML 表格classlabel-sheet-table按n_rows×n_cols双重循环生成tr/td单元格每个单元格的 CSS 类带有行号与列号label-sheet-row-{row}、label-sheet-col-{col}用于后续精确绝对定位被跳过的标签items[idx] is None渲染为空单元格label-sheet-cell-skip不打印任何内容从而实现偏移打印正常标签通过label.render_as_string(items[idx], request, insert_page_styleFalse)渲染为 HTML 片段——注意这里禁用了模板的page样式避免与整页的页面样式冲突单枚标签渲染抛出的异常会被捕获并记录日志同时该单元格渲染为红色错误块label-sheet-cell-errorbackground-color: #F00便于在 DEBUG 阶段定位问题模板。阶段四整页 CSS 定位与 PDF 生成wrap_pages方法将各页 HTML 拼接为单一文档并在head中注入整页样式每个单元格的绝对定位偏移按行号 × 标签高度、列号 × 标签宽度逐行逐列生成单位 mm.label-sheet-row-{row} { top: {row * label_height}mm; }.label-sheet-col-{col} { left: {col * label_width}mm; }page规则按page_width×page_heightmm设定纸张大小margin按选项设定表格page-break-after: always实现每页强制分页border-spacing: 0mm、padding: 0mm保证网格对齐开启border选项时单元格获得1px solid #000边框关闭时0mm无边框。最后按 DEBUG 设置分派输出if str2bool(self.get_setting(DEBUG)): generated_file ContentFile(html_data, labels.html) # 原始 HTML else: html weasyprint.HTML(stringhtml_data, url_fetcherInvenTreeURLFetcher()) document html.render().write_pdf() generated_file ContentFile(document, labels.pdf) # 渲染 PDF output.mark_complete(progressn_labels, outputgenerated_file)正常模式下HTML 通过WeasyPrint渲染为 PDF使用InvenTreeURLFetcher作为 URL 抓取器支持标签模板中引用的资源产物以labels.pdf命名保存并标记任务完成。与默认标签插件的对比为了更清晰地理解 Label Sheet 插件的定位这里将其与内置的默认 PDF 标签插件InvenTreeLabel进行对比维度InvenTreeLabel默认InvenTreeLabelSheet本文主题实现文件inventree_label.pylabel_sheet.py输出形态每枚标签渲染后通过PdfWriter拼接为纵向串联的单页序列PDF多枚标签按网格排列在单张纸上生成整页 PDF实现方式沿用混入类默认的print_label逐枚渲染流程before_printing/get_generated_file拼接结果整体重写print_labels自行计算网格、分页与定位打印选项仅 DEBUG 设置无额外打印选项DEBUG 设置 五个打印选项页面大小/跳过/边框/横向/页边距适用场景单标签独立成页、标签尺寸较大标准整页标签纸批量铺排两者都实现LabelPrintingMixin与SettingsMixin均提供 DEBUG 原始 HTML 输出模式且都设置BLOCKING_PRINT True同步返回打印结果。总结InvenTree Label Sheet 插件以整页网格排版的方式扩展了默认标签打印能力用户只需选择模板与插件、按需调整五个打印选项即可在 A4/Letter 等标准纸上批量打印标签。其核心价值在于免手动配置网格——行列数完全由标签尺寸、页面尺寸与页边距自动推导同时通过skip选项解决标签纸偏移问题通过 DEBUG 模式辅助模板排错。如需深入了解插件混入类的通用机制如自定义打印选项序列化器、print_label与print_labels的分工、BLOCKING_PRINT的异步打印行为可继续阅读 标签打印混入类文档或直接阅读 label_sheet.py 源码。【免费下载链接】InvenTreeOpen Source Inventory Management System项目地址: https://gitcode.com/GitHub_Trending/in/InvenTree创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考