Django DRF中MultipleObjectsReturned错误及office_serial异常递增求助
问题原因分析:创建ClearanceItem时ClearingOffice字段批量递增及查询错误
核心问题总结
创建ClearanceItem时出现两个异常:
- 抛出
get() returned more than one ClearingOffice -- it returned 14!查询错误 - 部分用户操作会导致所有ClearingOffice的
office_serial被批量递增,而非仅用户关联的那一个
具体原因分析
1. 使用非唯一字段office_serial作为查询条件,匹配多条记录
在signals.py的信号处理函数中,你通过office_serial定位要更新的ClearingOffice:
ClearingOffice.objects.get(office_serial=instance.office.office_serial).update(office_serial=F('office_serial') + 1)
ClearingOffice模型里,office_serial只是普通IntegerField,没有设置unique=True约束,这意味着多个ClearingOffice实例可能有相同的office_serial值。调用get()时,若匹配到多条记录就会抛出get() returned more than one错误;如果实际执行时误用了filter(),就会批量更新所有匹配该office_serial的记录。
2. 错误的模型实例更新方式
get()返回单个模型实例,而update()是Django QuerySet的方法,单个实例无法直接调用update()。你说有一个用户操作正常,大概率是该用户关联的ClearingOffice的office_serial恰好是唯一值,get()能拿到单个实例,此时代码可能被Django的机制意外兼容;但其他用户的office_serial不唯一时,就会触发批量更新或查询错误。
3. 冗余且错误的查询逻辑
每个ClearanceItem关联的office本身就是目标ClearingOffice实例,完全不需要通过office_serial二次查询。绕用非唯一字段查询,既增加了数据库操作,又引入了匹配多条数据的风险。
修复参考
- 修改信号处理逻辑,直接使用关联的
instance.office:
@receiver(post_save, sender=ClearanceItem) def create_transaction_log(sender, instance, created, **kwargs): if created: # 无需重复查询ClearanceItem,直接传入instance TransactionLog.objects.create( cl_itemid=instance, trans_desc="Add Clearance Item", trans_recorded=datetime.now().strftime('%Y-%m-%d') ) # 直接更新关联的office实例 instance.office.office_serial = F('office_serial') + 1 instance.office.save(update_fields=['office_serial'])
- 若
office_serial需要作为唯一标识,可在模型中添加unique=True约束:
class ClearingOffice(models.Model): # ...其他字段 office_serial = models.IntegerField(blank=True, null=True, unique=True)
内容的提问来源于stack exchange,提问作者Michael
相关产品推荐
相关产品推荐

