ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

InvenTree Label Machine 插件:基于机器接口的标签打印指南

InvenTree Label Machine 插件:基于机器接口的标签打印指南 InvenTree Label Machine 插件基于机器接口的标签打印指南【免费下载链接】InvenTreeOpen Source Inventory Management System项目地址: https://gitcode.com/GitHub_Trending/in/InvenTreeInvenTree Label Machine Plugin是 InvenTree 内置的标签打印插件它通过 InvenTree 的 machines 接口 将标签直接发送到外部标签打印机。阅读本文后你将理解该插件在标签打印链路中的定位、它的激活与配置方式、完整的打印调用流程以及如何编写自定义打印机驱动让任意型号的标签打印机接入 InvenTree。插件定位通用的打印机调度层而非具体的打印机驱动InvenTree Label Machine Plugin的核心价值在于解耦标签生成与硬件打印两个环节。根据 inventree_label_machine.md 的说明它允许标签通过 machines 接口直接打印到外部标签打印机插件本身不提供对任何具体标签打印机的连接能力它只是提供了一个面向所有已配置机器的通用打印接口实际与打印机的物理连接由另一个独立的驱动插件提供。这种设计对应 InvenTree 的机器架构详见 machines 总览文档内置的机器注册表machine registry管理所有已配置的机器机器类型machine type定义连接能力而驱动driver则由启用中的插件提供并继承对应机器类型的基础驱动类。从源码结构看该插件位于 src/backend/InvenTree/plugin/builtin/labels/inventree_machine.py类名为InvenTreeLabelPlugin并同时继承LabelPrintingMixin标签打印混合类与InvenTreePlugin插件基类class InvenTreeLabelPlugin(LabelPrintingMixin, InvenTreePlugin): Builtin plugin for machine label printing. This enables machines to print labels. NAME InvenTreeLabelMachine TITLE _(InvenTree machine label printer) DESCRIPTION _(Provides support for printing using a machine) VERSION 1.0.0 AUTHOR _(InvenTree contributors)其中NAME InvenTreeLabelMachine正是官方文档中提到的插件标识UI 上选择标签打印插件时看到的正是这个名称。激活方式强制内置插件始终启用文档明确指出This plugin is amandatoryplugin, and is always enabled.该插件属于强制mandatory插件无需手动启用服务器启动时即注册到插件注册表。测试代码 test_label_mixin.py 中对此有直接验证plugins registry.with_mixin(PluginMixinEnum.LABELS, activeTrue) self.assertEqual(len(plugins), 2) slugs [p.slug for p in plugins] self.assertIn(inventreelabel, slugs) self.assertIn(inventreelabelmachine, slugs)测试确认在启用状态下存在两个标签打印插件默认的inventreelabel生成 PDF 供下载以及本文主角inventreelabelmachine通过机器打印。插件设置无任何可配置项官方文档注明This plugin has no configurable settings.这意味着管理员无需在该插件上做任何配置。相关的参数如打印机选择、每张标签的打印份数等都在打印时由打印选项printing options动态提供而机器本身的配置如位置则归属于对应的机器实例与驱动详见下文。这进一步印证了该插件作为通用调度层的设计——它的行为完全由所选的机器与驱动决定。使用方式两步选择即打即用根据 inventree_label_machine.md 的使用说明打印标签时的操作流程为打印标签时在可用插件列表中选择InvenTreeLabelMachine选项然后从可用机器列表中选择目标打印机machine。结合 标签打印混合类文档 与界面截图可知打印界面会先选择标签模板Label Template再选择打印机Printer。在选择了机器类插件后界面会列出该用户可用的全部打印机并在打印选项中呈现机器的动态配置字段。需要特别注意的是只有机器machine已经被正确创建、配置并且激活才会出现在可选列表中。机器的创建与管理通过机器管理界面完成相关概念详见 Label Printer 机器类型文档 与 machines 总览文档。源码级解析一次机器标签打印的完整调用链1. 打印入口print_labels当用户在前端触发打印后InvenTree 会调用该插件的print_labels方法实现见 inventree_machine.py。其核心流程是def print_labels(self, label: LabelTemplate, output, items, request, **kwargs): machine, driver get_machine_and_driver( kwargs[printing_options].get(machine, ) ) # ... offload_task( call_machine_function, machine.pk, print_labels, label, items, outputoutput, force_syncsettings.TESTING or driver.USE_BACKGROUND_WORKER, groupplugin, **print_kwargs, )关键点如下从printing_options中取出machine字段解析出机器实例与驱动实例将实际打印工作通过offload_task投递到后台任务队列调用call_machine_function是否同步执行由force_sync决定其值为settings.TESTING or driver.USE_BACKGROUND_WORKER。也就是说在测试环境下强制同步否则遵循驱动定义的USE_BACKGROUND_WORKER标志该标志见 label_printer.py默认True即默认在后台 worker 中执行打印打印任务投递成功后output.mark_complete()会立刻标记该打印任务完成前端无需等待实际打印过程提升交互体验。2. 机器解析get_machine_and_driver在 inventree_machine.py 中辅助函数get_machine_and_driver负责把机器主键pk解析为机器与驱动对象通过机器注册表的registry.get_machine(machine_pk)获取机器实例校验machine.SLUG label-printer确保目标是标签打印机机器类型详见 label_printer.py返回机器及其驱动实例。由于machine选择字段本身带有校验器validator理论上这里不会出现非法值因此错误分支都被标记为# pragma: no cover不参与覆盖率统计的防御性代码。3. 底层转发call_machine_function后台任务最终调用 machine/registry.py 中的call_machine_functionmachine_registry_entrypoint() def call_machine_function(self, machine_id: str, function_name: str, *args, **kwargs): machine self.get_machine(machine_id) driver machine.driver func getattr(driver, function_name) return func(machine, *args, **kwargs)该函数根据机器 UUID 找到机器实例取回其驱动然后以机器为第一个参数调用驱动的print_labels或print_label方法。这即是插件只做调度、驱动负责落地的最终体现。4. 打印选项序列化器动态列出打印机与驱动选项InvenTreeLabelPlugin.PrintingOptionsSerializerinventree_machine.py实现了打印界面的动态表单machine字段ChoiceField其选项在__init__中动态生成——遍历注册表中所有label-printer类型的驱动registry.get_drivers(label-printer)调用每个驱动的get_printers()收集可用打印机打印机显示名由get_printer_name生成若机器配置了位置则显示为打印机名 位置名的格式默认值如果有可用打印机默认选中第一台并在其为最近使用时附加(last used)标记driver_options字段一个DependentField依赖machine字段的选择结果通过get_driver_options动态返回所选驱动定义的打印选项序列化器如打印份数copies等。这段实现对应了文档所述选择机器的交互——机器的候选列表完全由已注册的驱动与已配置的机器实例决定。5. 最近使用的打印机Last Used Printers为了提升使用体验插件会为每个用户记忆最近使用的打印机实现见 inventree_machine.py 与print_labels内联逻辑使用用户设置LAST_USED_PRINTING_MACHINES保存最近使用过的机器主键列表每次打印成功后将当前机器移动到列表头部只保留最近 10 台避免列表无限增长打印选项序列化器初始化时会按该列表对候选打印机排序把最近使用的机器排在前面。Label Printer 机器类型状态、设置与选项要理解该插件如何与具体打印机对接需要了解 LabelPrinterMachine 机器类型机器类型定义SLUG label-printerNAME Label PrinterDESCRIPTION Directly print labels for various items.基础驱动为LabelPrinterBaseDriver机器设置MACHINE_SETTINGS内置了LOCATION选项可将打印机限定到某个库存位置stock.stocklocation用于按位置筛选打印机。状态码MachineStatus每台打印机都有预定义的状态码默认状态为UNKNOWN由驱动在实际运行中更新详见 label_printer.py状态码含义CONNECTED (100)打印机已连接并准备就绪UNKNOWN (101)状态未知如无活动连接默认状态PRINTING (110)正在打印标签WARNING (200)处于未知警告状态NO_MEDIA (301)耗材用尽如标签纸卷为空PAPER_JAM (302)卡纸DISCONNECTED (400)驱动无法与打印机建立连接ERROR (500)处于未知错误状态状态可通过machine.set_status(...)与machine.set_status_text(...)更新见 machines 总览文档 的 Machine Status 一节。默认打印选项LabelPrinterBaseDriver.PrintingOptionsSerializerlabel_printer.py内置了一个通用选项copies默认值为 1表示每张标签打印的份数。自定义驱动可以继承该序列化器并添加自己的选项。基础驱动提供的渲染辅助方法LabelPrinterBaseDriver还提供了若干渲染辅助方法详见 label_printer.mdrender_to_pdf、render_to_pdf_data、render_to_html、render_to_png驱动可在打印前将标签模板渲染为 PDF/HTML/PNG 数据后再发送给物理打印机。如何让具体打印机接入编写自定义驱动正如文档反复强调的该插件不会连接任何具体打印机实际连接需要独立驱动插件。根据 Label Printer 机器类型文档 的说明编写自定义标签打印机驱动需要编写一个实现了MachineDriverMixin的插件见 machine 混合类文档并在get_machine_drivers方法中返回驱动类列表驱动类继承LabelPrinterBaseDriver至少实现print_label或print_labels方法。一个最小化的驱动骨架如下参考 machines 总览文档 中的示例驱动from plugin.mixins import MachineDriverMixin from plugin import InvenTreePlugin from machine.machine_types.label_printer import LabelPrinterBaseDriver class MyLabelDriver(LabelPrinterBaseDriver): SLUG my-label-driver NAME My Label Driver DESCRIPTION Print labels to my physical label printer def print_label(self, machine, label, item, **kwargs): # 在这里实现与物理打印机的通信 # 例如渲染标签、发送打印指令 pass class MyLabelDriverPlugin(MachineDriverMixin, InvenTreePlugin): NAME MyLabelDriverPlugin SLUG my-label-driver-plugin TITLE My Label Driver Plugin def get_machine_drivers(self): return [MyLabelDriver]几点关键实现提示LabelPrinterBaseDriver定义了required_overrides [[print_label, print_labels]]label_printer.py即驱动至少要实现两个打印方法之一否则机器初始化会失败若驱动希望自定义打印选项可继承PrintingOptionsSerializer并添加字段例如class MyLabelDriver(LabelPrinterBaseDriver): # ... class PrintingOptionsSerializer(LabelPrinterBaseDriver.PrintingOptionsSerializer): auto_cut serializers.BooleanField( defaultTrue, label_(Auto cut), help_text_(Automatically cut the label after printing), )驱动可以在MACHINE_SETTINGS中定义自己的机器设置项并支持required: True标记——必填项未配置时该机器将无法启动见 machines 总览文档 的 Settings 一节。生产环境注意事项由于该插件把打印任务投递到后台 worker 执行涉及跨进程共享机器注册表与机器状态根据 machines 总览文档 的说明在生产环境配合 worker 使用机器功能时必须配置共享的 Redis 缓存详见 进程管理文档;注册表、驱动与机器状态状态码、错误信息等存储在缓存中默认的本地内存缓存无法跨进程共享当存在 worker 时会同时存在多个注册表实例每个 worker 线程与主线程各一份但init_machine等初始化与更新钩子只会由主进程调用一次。参考资源插件官方文档docs/docs/plugins/builtin/inventree_label_machine.md插件实现源码src/backend/InvenTree/plugin/builtin/labels/inventree_machine.pyLabel Printer 机器类型src/backend/InvenTree/machine/machine_types/label_printer.py机器注册表与调用转发src/backend/InvenTree/machine/registry.py机器机制总览docs/docs/plugins/machines/overview.mdLabel Printer 机器类型指南docs/docs/plugins/machines/label_printer.md标签打印混合类docs/docs/plugins/mixins/label.md插件级测试验证src/backend/InvenTree/plugin/base/label/test_label_mixin.py【免费下载链接】InvenTreeOpen Source Inventory Management System项目地址: https://gitcode.com/GitHub_Trending/in/InvenTree创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表