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

Django获取ForeignKey ID时出现TypeError无法解包非可迭代对象问题

问题原因

你代码里invoice视图函数的这一行写法错误:

cust_id = Invoice.objects.get(id, customers=customer.id)

Django的ORM get()方法要求所有筛选条件都以关键字参数形式传入,你这里直接写id是把Python内置的id()函数作为位置参数传给了get(),get()方法无法解析这个函数对象,所以抛出了TypeError: cannot unpack non-iterable builtin_function_or_method object错误。
而且你这里完全不需要再查询一次数据库:调用Invoice.objects.create()的时候会直接返回刚创建的Invoice实例,直接复用即可。

修复方案

1. 修复当前报错

把视图里创建发票后的查询代码删掉,直接复用create返回的实例:

# 原来的创建代码保留
new_invoice = Invoice.objects.create(
    products = product,
    quantity = qt, 
    total=total, 
    customers = customer
)
# 删掉原来的 Invoice.objects.get 那一行,直接用new_invoice取值
product_name = new_invoice.products
product_quantity = new_invoice.quantity
product_total = new_invoice.total

2. 调整模型满足「同一张发票添加多个产品」的需求

你现在的模型设计有问题:Invoice和Product用ForeignKey关联,意味着一张发票只能对应一个产品,不符合你的需求。需要新增中间表InvoiceItem存储发票下的每个商品条目:

修正后的models.py

from django.db import models
from account.models import Customer
from product.models import Product

# 发票主表:一张发票对应一个客户,包含多个商品
class Invoice(models.Model):
    customer = models.ForeignKey(Customer, on_delete=models.CASCADE, verbose_name="所属客户")
    date = models.DateTimeField(auto_now_add=True, verbose_name="开票日期")
    total_amount = models.BigIntegerField(default=0, verbose_name="发票总金额")

    class Meta:
        verbose_name = "发票"
        verbose_name_plural = verbose_name

# 发票商品条目:关联发票和商品,存储单个商品的购买信息
class InvoiceItem(models.Model):
    invoice = models.ForeignKey(Invoice, on_delete=models.CASCADE, related_name="items", verbose_name="所属发票")
    product = models.ForeignKey(Product, on_delete=models.CASCADE, verbose_name="商品")
    quantity = models.IntegerField(default=1, verbose_name="购买数量")
    item_total = models.BigIntegerField(default=0, verbose_name="该商品总金额")

    class Meta:
        verbose_name = "发票商品条目"
        verbose_name_plural = verbose_name

3. 实现「按客户ID筛选所有发票」的需求

模型调整后,只需要用ORM的filter方法即可查询指定客户的所有发票:

# 示例:查询客户id为1的所有发票
customer_invoices = Invoice.objects.filter(customer_id=1)
# 还可以预加载发票下的所有商品,减少查询次数
customer_invoices = Invoice.objects.filter(customer_id=1).prefetch_related("items")

4. 其他优化建议

  • 字段命名尽量见名知意,customers改为customer(一张发票只对应一个客户,用单数更合理)
  • 用get_object_or_404替代直接get(),避免查询不到对象时抛出500错误
  • 操作session前先判断customerId是否存在,避免未走billingform直接访问invoice视图时报错

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 21:27:01