资讯动态

InvenTree Locate Mixin 插件开发指南:为库存项目与库存位置实现自定义定位能力

发布时间:2026/9/17 4:39:42 来源:尧图企业网站定制
InvenTree Locate Mixin 插件开发指南为库存项目与库存位置实现自定义定位能力【免费下载链接】InvenTreeOpen Source Inventory Management System项目地址: https://gitcode.com/GitHub_Trending/in/InvenTree导读LocateMixin是 InvenTree 开放库存管理系统Open Source Inventory Management System提供的一类插件混入Mixin它允许第三方插件通过完全自定义的方式定位Locate某个库存项目StockItem或库存位置StockLocation。例如仓库中每个料箱配有 LED 与蜂鸣器定位某件库存时触发声光提示或接入自动化取料系统把目标物料通过传送带送达用户面前。读完本文你将掌握LocateMixin的完整使用流程如何在 InvenTree 中编写并激活一个定位插件、其两个核心方法locate_stock_item/locate_stock_location的签名与默认行为、Web 端与移动 App 端如何调用该能力以及底层 API 端点api-locate-plugin的请求/响应契约。LocateMixin 是什么LocateMixin是定义在 src/backend/InvenTree/plugin/base/locate/mixins.py 中的一个混入类其设计目的非常聚焦让插件接管如何把某个库存实体定位给操作人员这件事。典型应用场景原文档给出了两个极有代表性的落地场景声光指引仓库按零件料箱排布每个料箱装有视听指示器如 RGB LED 与蜂鸣器。当系统定位某一库存项目时对应料箱的 LED 闪烁、蜂鸣器响起帮助拣货员快速锁定目标。自动取料接入零件取回parts retrieval系统定位某个库存项目时系统把该库存通过传送带直接送达用户面前。官方文档对此的评价是 The possibilities are endless!可能性是无穷的这正体现了该 Mixin 的设计哲学InvenTree 只定义调用契约把具体定位手段完全交给插件实现——无论是灯光、声音、传送带还是机械臂。Mixin 的注册机制从源码看LocateMixin在初始化时通过self.add_mixin(PluginMixinEnum.LOCATE, True, __class__)将自身注册进插件混入枚举PluginMixinEnum.LOCATE见 mixins.py并声明MIXIN_NAME Locate。这意味着插件注册表registry可以通过registry.with_mixin(PluginMixinEnum.LOCATE)筛选出所有支持定位能力的插件该判断是前端按钮显隐、后端 API 校验共同依赖的基础。LocateMixin同时通过 src/backend/InvenTree/plugin/mixins/init.py 统一导出因此插件代码中可直接from plugin.mixins import LocateMixin与其它 MixinActionMixin、BarcodeMixin、EventMixin等保持一致的导入习惯。两个核心方法方法签名与默认行为LocateMixin向插件暴露两个可选覆写的方法各自承担一类定位职责locate_stock_item(item_pk)定位库存项目def locate_stock_item(self, item_pk): Attempt to locate a particular StockItem. Arguments: item_pk: The PK (primary key) of the StockItem to be located 默认实现源码 mixins.py的逻辑是降级转发记录一条logger.info(LocateMixin: Attempting to locate StockItem pk%s, item_pk)日志通过StockItem.objects.get(pkitem_pk)查询目标库存项目仅当该项目在库item.in_stock且已分配库位item.location is not None时把定位动作转发给self.locate_stock_location(item.location.pk)若库存项目不存在记录logger.warning(...)后静默返回。也就是说未覆写时定位一个库存项目等价于定位它所在的库存位置。注释明确指出 A custom implementation could always change this behaviour——自定义实现完全可以改变这一行为例如按料箱号直接驱动硬件而非转发到位置定位。locate_stock_location(location_pk)定位库存位置def locate_stock_location(self, location_pk): Attempt to location a particular StockLocation. Arguments: location_pk: The PK (primary key) of the StockLocation to be located 默认实现什么都不做直接抛出MixinNotImplementedError见 mixins.py。这一设计非常关键MixinNotImplementedError由plugin.helpers提供用于标记该混入要求插件必须实现的能力单元测试 test_locate.py 中验证了这一点定义了一个空实现的SamplePlugin(LocateMixin, InvenTreePlugin)后调用locate_stock_item(1)会一路转发到locate_stock_location(1)并最终抛出MixinNotImplementedError而传入一个不存在的 PK999则由于StockItem.DoesNotExist被静默捕获不会抛错。结论一个真正可用的定位插件至少应当覆写locate_stock_location如果希望直接定位到具体料箱还应同时覆写locate_stock_item。编写一个定位插件从示例插件看最小实现仓库在 src/backend/InvenTree/plugin/samples/locate/locate_sample.py 中提供了一个可直接参考的示例插件SampleLocatePlugin原文档亦推荐读者直接阅读该源码。需要注意该插件的注释特别声明This plugin does notactuallylocate anything!——它只把定位信息写入日志与元数据作为演示用脚手架。插件骨架import structlog from plugin import InvenTreePlugin from plugin.mixins import LocateMixin logger structlog.get_logger(inventree) class SampleLocatePlugin(LocateMixin, InvenTreePlugin): A very simple example of the locate plugin. NAME SampleLocatePlugin SLUG samplelocate TITLE Sample plugin for locating items VERSION 0.2要点插件类需多重继承LocateMixin与InvenTreePlugin继承顺序为(LocateMixin, InvenTreePlugin)NAME、SLUG、TITLE、VERSION是 InvenTree 插件的基础元信息其中SLUG此处为samplelocate会被用于后续 API 调用中指定插件因此必须唯一。覆写locate_stock_itemdef locate_stock_item(self, item_pk): from stock.models import StockItem logger.info(SampleLocatePlugin attempting to locate item ID %s, item_pk) try: item StockItem.objects.get(pkitem_pk) logger.info(StockItem %s located!, item_pk) # Tag metadata item.set_metadata(located, True) except (ValueError, StockItem.DoesNotExist): logger.exception(StockItem ID %s does not exist!, item_pk)示例做了两件事记录已定位日志并调用set_metadata(located, True)把元数据标签写到库存项目上。这个元数据写入正是单元测试的断言依据见下文测试部分。覆写locate_stock_locationdef locate_stock_location(self, location_pk): from stock.models import StockLocation logger.info( SampleLocatePlugin attempting to locate location ID %s, location_pk ) try: location StockLocation.objects.get(pklocation_pk) logger.info(Location exists at %s, location.pathstring) # Tag metadata location.set_metadata(located, True) except (ValueError, StockLocation.DoesNotExist): logger.exception(Location ID %s does not exist!, location_pk)这里还打印了库存位置的可读路径location.pathstring可用于调试与日志归档。真实硬件场景下你该覆写什么把示例插件中的写日志 写元数据替换成实际的硬件驱动调用即可完成真机对接例如在locate_stock_location中根据location_pk或自定义扩展字段如料箱编号触发对应料箱的 GPIO 电平点亮 LED、鸣响蜂鸣器在locate_stock_item中先查询库存项目再根据其库位下发机械臂/传送带指令。Web 端集成前端按钮与 API 端点触发入口Web 界面在 InvenTree 新版 React 前端中定位入口由 src/frontend/src/components/plugins/LocateItemButton.tsx 提供组件通过usePluginsWithMixin(locate)拉取所有启用且支持locate混入的插件只有当存在可用的定位插件时按钮才会渲染locatePlugins.length 0时返回null同时要求传入了stockId或locationId中的至少一个按钮以雷达图标IconRadar展示tooltip 为 Locate Item点击后弹出表单plugin字段以下拉选择形式列出可用定位插件item与location作为隐藏字段携带当前上下文 ID提交后向ApiEndpoints.plugin_locate_item发送POST请求成功提示 Item location requested。原文档中的 Web 截图web_locate.png展示了库存项目详情页面上identify stock item识别/定位库存项目操作按钮的位置与形态后端 API 端点api-locate-pluginWeb 与 App 最终都会调用同一个后端端点。路由注册于 src/backend/InvenTree/plugin/api.pypath(locate/, LocatePluginView.as_view(), nameapi-locate-plugin)即完整 URL 为/api/plugin/locate/。端点的核心实现在 src/backend/InvenTree/plugin/base/locate/api.py其post方法处理流程如下读取plugin参数缺失则抛出ParseError(plugin field must be supplied)校验插件通过registry.with_mixin(PluginMixinEnum.LOCATE)过滤出所有定位插件若请求的plugin传入的是插件slug不在其中返回 400 与错误信息Plugin xxx is not installed, or does not support the location mixin校验目标itemStockItem 主键优先级高于locationStockLocation 主键两者都缺省时返回 400Must supply either item or location parameter传入的 PK 对应记录不存在时返回 404StockItem matching PK 1 not found这类信息异步下发校验通过后通过offload_task(call_plugin_function, plugin, locate_stock_item, item_pk, groupplugin)把定位动作离线投递到后台任务队列执行——这正是 InvenTree 对耗时硬件操作LED 闪烁、传送带运行的标准处理方式避免阻塞 HTTP 请求返回结果返回 200 与{success: Identification plugin activated, plugin: plugin, item: item_pk}或location结构。其中offload_task与call_plugin_function的配合也解释了为何 API 只负责校验并触发而非等待完成定位动作是异步的、即发即返回的。App 端集成如果安装了定位插件并激活InvenTree 移动端 App 同样会为库存项目StockItem或库存位置StockLocation显示一个定位按钮。原文档给出的 App 截图app_locate.png展示的是 App 中 Stock Location 详情页的 Locate stock location 入口App 端与 Web 端共享同一套LocateMixin能力与api-locate-plugin端点插件作者无需为移动端编写任何额外代码——只要插件安装并激活两个终端会自动获得定位入口这正是一次实现、多端生效的集成优势。单元测试理解调用链与边界行为示例插件测试 test_locate_sample.pySampleLocatePluginTests.test_run_locator完整覆盖了 API 的成功与失败路径请求体预期状态码说明{}400未提供插件{plugin: sampleevent}400插件未安装或不支持定位混入{plugin: samplelocate}400缺少item/location{plugin: samplelocate, item: 999}404库存项目不存在{plugin: samplelocate, item: 1}200正常触发定位库存项目{plugin: samplelocate, location: 999}404库存位置不存在{plugin: samplelocate, location: 1}200正常触发定位库存位置测试使用fixtures [location, category, part, stock]加载库存相关基础数据并通过registry.get_plugin(samplelocate, ...)激活插件。混入测试 test_locate.pyLocatePluginTests验证了更底层的契约test_installed断言registry.with_mixin(PluginMixinEnum.LOCATE)至少包含一个插件且samplelocate在列test_locate_fail系统化验证 400/404 的各类失败组合包括item或location传入非法 PKqq、99999、-42时返回 404test_locate_item/test_locate_location先给实体写入metadata[located] False调用定位 API 后刷新数据库断言metadata[located]变为True——直接证明了示例插件中set_metadata(located, True)确实被后台执行。测试注释说明由于单元测试环境中没有后台 worker定位函数会被内联inline执行test_mixin_locate验证空实现的locate_stock_item(1)会转发到locate_stock_location(1)并抛出MixinNotImplementedError。快速上手清单实现插件创建插件目录与__init__.py插件类继承(LocateMixin, InvenTreePlugin)至少覆写locate_stock_location按需覆写locate_stock_item具体硬件逻辑可参考 locate_sample.py 的骨架。安装并激活将插件放入 InvenTree 插件目录或通过插件安装机制引入在管理界面启用激活后registry.with_mixin(PluginMixinEnum.LOCATE)即可检索到它。验证 API向/api/plugin/locate/发送POST请求体形如{plugin: samplelocate, item: 1}或{plugin: samplelocate, location: 1}观察 200/400/404 行为是否与上文测试矩阵一致。多端生效插件激活后Web 端库存详情页会出现雷达图标定位按钮移动 App 端也会显示对应的定位入口无需额外编码。生产对接将示例中的日志/元数据逻辑替换为真实硬件驱动调用并注意借助后台任务机制offload_task执行耗时操作。小结LocateMixin是 InvenTree 插件体系中一个小而美的接口抽象它以两个方法locate_stock_item、locate_stock_location、一套 API 端点api-locate-plugin和一个注册机制PluginMixinEnum.LOCATE定义了定位库存的通用契约把声光指引、自动取料等千差万别的硬件实现完全留给插件。理解其默认转发逻辑定位库存项目→定位其所在位置、MixinNotImplementedError的约束语义以及前端按钮与后台任务的触发链路你就能以最低成本把 InvenTree 与自己的仓库硬件体系打通。【免费下载链接】InvenTreeOpen Source Inventory Management System项目地址: https://gitcode.com/GitHub_Trending/in/InvenTree创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价