Django中根据字段选择动态更新另一关联字段值的实现问题
Django发票表单选中商品自动填充单价实现方案
问题背景
- 已定义两个Django业务模型:
Inventory:商品存储模型,主键为product_number,包含product、title、amount(商品基准单价)字段Invoice:发票模型,主键为invoice_number,最多支持录入10行商品条目,每行通过外键关联Inventory商品,额外配置购买数量、成交单价、行总价字段
- 核心需求:新增发票表单中,用户在任意行的商品下拉选择框选中对应商品时,自动将该商品的基准单价填充到同行的
unit_price(单价)输入框 - 前期实现踩坑:
- 首次编写逻辑后,选中商品时单价输入框仅显示
{字符 - 调整JS代码后抛出
Uncaught TypeError: Cannot read properties of undefined (reading '1')报错,已知下拉框选中值为关联商品的主键,定位为前端读取JSON数据的结构逻辑错误
- 首次编写逻辑后,选中商品时单价输入框仅显示
可直接复用的实现方案
1. 后端视图层数据预处理
不要直接把原始QuerySet传给模板序列化,提前把数据处理成以商品主键为key、单价为value的映射结构,省去前端遍历查找的逻辑,从根源上避免结构读取错误:
from django.shortcuts import render from .models import Inventory def add_invoice(request): # 仅提取需要的字段,减少不必要的数据传输 inventory_price_map = { item["product_number"]: item["amount"] for item in Inventory.objects.values("product_number", "amount") } return render(request, "invoice_add.html", { "inventory_price_map": inventory_price_map, # 其余表单所需上下文参数正常传入 })
2. 模板层安全注入数据
使用Django内置的json_script模板标签注入数据,标签会自动完成转义、避免XSS风险,不会出现JSON格式解析问题:
<!-- 放在表单域之后、JS脚本之前即可,id属性可自定义,后续JS读取时对应即可 --> {{ inventory_price_map|json_script:"inventory-price-data" }}
3. 前端交互逻辑
先正确解析注入的JSON数据为JS对象,再逐行给商品下拉框绑定变更事件,通过行号匹配对应单价输入框完成赋值:
// 读取并解析注入的商品单价映射 const priceMap = JSON.parse(document.getElementById("inventory-price-data").textContent); // 逐行绑定事件(适配最多10行商品的规则) for (let lineIndex = 1; lineIndex <= 10; lineIndex++) { // 注意选择器里的name属性要和你表单实际渲染的字段name保持一致 const productSelector = document.querySelector(`select[name="line_${lineIndex}_product"]`); const priceInput = document.querySelector(`input[name="line_${lineIndex}_unit_price"]`); // 跳过不存在的行(比如部分场景默认只显示3行,其余行动态新增) if (!productSelector || !priceInput) continue; productSelector.addEventListener("change", function() { const selectedPid = this.value; // 未选中商品时清空单价 if (!selectedPid) { priceInput.value = ""; return; } // 直接从映射表取对应单价,无匹配值则留空 priceInput.value = priceMap[selectedPid] ?? ""; // 需要自动计算行总价的话,在这里加数量*单价的计算逻辑即可 }); }
之前报错的根因
- 选中商品后单价显示
{:没有将序列化后的JSON字符串正确解析为JS对象,直接把字符串赋值给输入框,最终只显示了字符串的第一个字符 - 读取undefined属性报错:之前传入的JSON是数组结构(QuerySet序列化默认是数组),直接用商品主键作为数组下标读取,自然会得到undefined值,再读取undefined的属性就会抛出类型错误;提前在后端处理成主键为key的映射结构即可完全避免这个问题
内容的提问来源于stack exchange,提问作者perpetualdarkness
相关产品推荐
相关产品推荐

