You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django自定义条码扫码校验:如何判断序列号不超GRN对应产品数量

核心问题根因

原代码存在三个逻辑漏洞,导致无法正确读取入库数量完成校验:

  • Grn.objects.filter() 返回的是Django查询集(QuerySet),不是单个模型实例,无法直接访问关联表的字段
  • Grn 模型的 items 是多对多关联字段,访问后返回的是关联的GrnItems查询集,不是单个明细行对象,直接通过items.item_quantity读取会触发字段不存在的报错
  • 缺少边界值防护:未处理GRN不存在、GRN下无对应商品的场景,也未对解析出的序列号做范围合法性判断
正确实现逻辑

不需要先查询Grn对象,直接从GrnItems明细模型出发,利用Django多对多的反向关联能力,一次查询同时匹配GRN ID、商品ID两个条件,取出对应明细行的入库数量完成校验,比先查GRN再查明细的写法减少一次数据库查询。
修正后的完整处理代码:

c = request.GET['code'].strip()
# 前置校验条码基础格式,避免索引解析错误
if len(c) != 16 or not c.startswith("YNT"):
    return HttpResponse("无效条码格式")

try:
    grn_id = int(c[3:7])
    product_id = int(c[7:11])
    serial_no = int(c[11:])
except ValueError:
    return HttpResponse("条码包含非法数字内容")

# 核心修正:直接查询匹配的GrnItems明细行
# 因Grn模型未自定义related_name,GrnItems到Grn的反向访问器为默认值grn_set
matched_item = GrnItems.objects.filter(
    grn_set__pk=grn_id,
    item__pk=product_id
).first()

# 处理匹配不到明细的异常场景
if not matched_item:
    return HttpResponse("条码对应的GRN或商品不存在")

total_stock = matched_item.item_quantity
# 序列号范围为1~总入库量(对应生成规则中j+1从1开始计数)
if 1 <= serial_no <= total_stock:
    res = Product.objects.get(pk=product_id).description
    # 后续扫码业务逻辑
else:
    return HttpResponse(f"序列号非法,该商品在本GRN下总入库{total_stock}件")
补充说明
  • 如果觉得反向关联名grn_set可读性差,可以在Grn模型的items字段定义中添加related_name="grn"参数,调整后GrnItems到Grn的反向访问器名会变为grn,查询时可以直接写grn__pk=grn_id,代码可读性更好。
  • 当前模型的多对多关联设计存在业务逻辑隐患:正常入库单的明细行是入库单的独有从属内容,同一明细行不应被多个入库单复用。建议将关联关系调整为一对多:在GrnItems中新增grn = models.ForeignKey(Grn, on_delete=models.CASCADE)字段,删除Grn模型中的items多对多字段,调整后上述查询逻辑完全兼容,且从结构上避免了明细被多单复用的逻辑漏洞。
  • 若业务中存在同一GRN下同一商品对应多条入库明细的场景,当前仅携带商品ID的条码规则会出现重复,需要在条码中补充GrnItems的主键字段做唯一区分。

内容的提问来源于stack exchange,提问作者Rahul Sharma

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.23 03:36:03