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

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二次查询。绕用非唯一字段查询,既增加了数据库操作,又引入了匹配多条数据的风险。


修复参考

  1. 修改信号处理逻辑,直接使用关联的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'])
  1. 若office_serial需要作为唯一标识,可在模型中添加unique=True约束:
class ClearingOffice(models.Model):
    # ...其他字段
    office_serial = models.IntegerField(blank=True, null=True, unique=True)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 09:35:35