创建CusOrder模型对象时自动生成ProductOut对象的报错解决
解决Django中创建CusOrder时自动生成ProductOut的错误问题
错误原因分析
报错<CusOrder: Asif> needs to have a value for field "id" before this many-to-many relationship can be used.的核心问题有两个:
- 对象未持久化:重写的
save方法里先创建ProductOut,再调用父类save,此时CusOrder还未存入数据库,没有生成主键id,但ProductOut的refrence是多对多关联CusOrder,无法绑定未保存的对象。 - 字段操作错误:
self.product.P_name写法错误,product是多对多字段,返回的是QuerySet集合,不能直接访问单个对象的属性;同时ProductOut的product字段需要传入Product对象,不是字符串。
正确实现流程
1. 调整模型设计(修正不合理关联)
原ProductOut的refrence用多对多不符合业务逻辑(一个出库记录应归属单个订单),改为外键:
class Category(models.Model): # 修正拼写错误:Catagory → Category name = models.CharField(max_length=60) def __str__(self): return self.name class Product(models.Model): P_name = models.CharField(max_length=30) stock_in = models.IntegerField(default=0) unit_price = models.IntegerField(default=0) cata = models.ForeignKey(Category, on_delete=models.CASCADE) def __str__(self): return self.P_name class ProductOut(models.Model): refrence = models.ForeignKey(CusOrder, on_delete=models.CASCADE) # 多对多改外键 stock_out = models.IntegerField(default=0) sell_price = models.IntegerField(default=0) product = models.ForeignKey(Product, on_delete=models.CASCADE) def __str__(self): return f"{self.refrence.cus_number} - {self.product.P_name}" class ReturnedProduct(models.Model): cus_number = models.ForeignKey(CusOrder, on_delete=models.CASCADE) product = models.ForeignKey(Product, on_delete=models.CASCADE) qty = models.IntegerField(default=0) def __str__(self): return f"{self.cus_number.cus_number} - {self.product.P_name}"
2. 重写CusOrder的save方法(确保对象先持久化)
先保存CusOrder到数据库生成主键,再处理关联和创建ProductOut:
class CusOrder(models.Model): cus_name = models.CharField(max_length=100) cus_number = models.CharField(max_length=11) product = models.ManyToManyField(Product) qty = models.IntegerField(default=0) sell_price = models.IntegerField(default=0) def __str__(self): return self.cus_name def save(self, *args, **kwargs): # 判断是否是新建订单(避免更新时重复创建出库记录) is_new_order = self.pk is None # 先保存订单到数据库,生成主键id super(CusOrder, self).save(*args, **kwargs) if is_new_order: # 遍历订单关联的所有产品,逐个创建出库记录 for prod in self.product.all(): ProductOut.objects.create( refrence=self, stock_out=self.qty, sell_price=self.sell_price, product=prod )
关键注意点
- 必须先调用父类
save方法,让CusOrder完成持久化,才能建立与ProductOut的关联; - 多对多字段
product是QuerySet集合,需用.all()遍历处理;如果业务中一个订单只能对应单个产品,建议将product字段改为外键更合理; - 添加
is_new_order判断,防止每次更新订单时重复创建ProductOut记录。
内容的提问来源于stack exchange,提问作者Asif Ahamed Fahim
相关产品推荐
相关产品推荐

