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

Django in_bulk序列化报'int'无'_meta'属性及下拉联动问题

问题修复方案

1. AttributeError: 'int' object has no attribute '_meta' 修复

报错核心原因是in_bulk()返回值不符合Django序列化器的入参规则:

  • Inventory.objects.in_bulk() 默认返回主键为键、模型实例为值的字典结构,而serializers.serialize()要求传入可迭代的模型实例集合(QuerySet、模型实例列表均可)。传入字典时序列化器会遍历拿到主键的int值,尝试访问模型专属的_meta属性时必然报错。

直接替换序列化代码即可:

from django.core import serializers
# 错误写法
# data = serializers.serialize("json", Inventory.objects.in_bulk())
# 正确写法1:直接传入查询集
data = serializers.serialize("json", Inventory.objects.all())
# 正确写法2:如果必须使用in_bulk,提取值转成实例列表传入
# data = serializers.serialize("json", list(Inventory.objects.in_bulk().values()))

2. 下拉联动赋值异常修复

2.1 选中项无法自动匹配对应单价

该问题通常由两个错误导致:一是下拉选项的value未正确绑定商品主键,或主键类型(字符串/数字)不匹配导致find方法匹配失败;二是未正确监听下拉框的change事件。

建议后端先将序列化数据整理为扁平结构再传给前端,减少前端处理逻辑:

# views.py
import json
from django.core import serializers

def add_invoice(request):
    # 每次请求重新查询最新库存数据,避免旧数据残留
    inventory_qs = Inventory.objects.all()
    # 序列化后转为原生Python对象,避免转义问题
    inventory_raw = json.loads(serializers.serialize("json", inventory_qs))
    # 提取前端需要的字段,简化匹配逻辑
    inventory_data = [
        {
            "id": item["pk"],
            "name": item["fields"]["name"], # 替换为你模型中的商品名称字段
            "price": item["fields"]["price"] # 替换为你模型中的单价字段
        } for item in inventory_raw
    ]
    return render(request, "add_invoice.html", {
        "inventory_data_json": json.dumps(inventory_data),
        "inventory_list": inventory_qs # 用于渲染下拉选项
    })

前端模板代码参考:

<!-- 下拉选择与单价输入组件 -->
<select id="inventorySelect" name="inventory">
    <option value="">请选择商品</option>
    {% for item in inventory_list %}
    <!-- option的value必须绑定主键,保证值类型一致 -->
    <option value="{{ item.pk }}">{{ item.name }}</option>
    {% endfor %}
</select>
<input type="number" id="priceInput" name="price" step="0.01">

<script>
// 注入后端传递的最新库存数据
const inventoryList = JSON.parse('{{ inventory_data_json|safe }}');
const selectEl = document.getElementById('inventorySelect');
const priceEl = document.getElementById('priceInput');

// 监听下拉框选中变化事件
selectEl.addEventListener('change', function() {
    const selectedId = Number(this.value); // 统一转为数字类型,避免类型不匹配
    if (!selectedId) {
        priceEl.value = '';
        return;
    }
    const matched = inventoryList.find(goods => goods.id === selectedId);
    if (matched) priceEl.value = matched.price;
});
</script>

2.2 数据更新后前端不同步

该问题是旧数据缓存导致:

  • 不要在视图函数外硬编码库存查询集,每次进入新增发票页面都要重新查询最新的Inventory数据序列化传入,不要给该视图加页面缓存
  • 开发调试时开启浏览器DevTools的「禁用缓存」选项,避免本地缓存的旧页面干扰
  • 如果是弹窗/局部加载的新增发票表单,不要复用已加载的旧DOM,每次打开表单时重新拉取最新库存数据,或重新渲染时注入最新的序列化结果。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 01:48:16