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

Django中根据字段选择动态更新另一关联字段值的实现问题

Django发票表单选中商品自动填充单价实现方案

问题背景

  • 已定义两个Django业务模型:
    • Inventory:商品存储模型,主键为product_number,包含product、title、amount(商品基准单价)字段
    • Invoice:发票模型,主键为invoice_number,最多支持录入10行商品条目,每行通过外键关联Inventory商品,额外配置购买数量、成交单价、行总价字段
  • 核心需求:新增发票表单中,用户在任意行的商品下拉选择框选中对应商品时,自动将该商品的基准单价填充到同行的unit_price(单价)输入框
  • 前期实现踩坑:
    1. 首次编写逻辑后,选中商品时单价输入框仅显示{字符
    2. 调整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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 20:18:19