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
相关产品推荐
相关产品推荐

