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

Django的get_or_create返回False或抛出IntegrityError的原因是什么

get_or_create两种返回结果的根本原因
  • 当get_or_create执行第一阶段的SELECT查询,用你传入的所有非defaults字段作为筛选条件,成功匹配到数据库中已有的记录时,会直接返回(匹配到的实例, False),不会执行后续创建逻辑,这就是你遇到的created=False的场景,属于正常的查询命中逻辑。
  • 当第一阶段SELECT查询没有匹配到记录,进入INSERT创建阶段时,写入操作触发了数据库层面的唯一约束校验,就会抛出IntegrityError,你的场景下触发的原因有两个:
    1. 查询参数与唯一约束不匹配:你的模型设置的联合唯一约束是account_name、date、target三个字段,但你调用get_or_create时,在非defaults参数里额外加了user作为查询条件。如果数据库中已经存在和你传入的account_name、date、target一致的记录,但这条记录的user字段值和你传入的user不同,第一阶段SELECT用四个字段联合查询就会查不到数据,进入INSERT阶段时就会触发唯一约束报错。
    2. 并发竞争(Race Condition):就算你把查询参数调整为和唯一约束完全匹配,在高并发场景下依然可能触发报错。因为get_or_create的查询和写入不是数据库层面的原子操作,两个请求同时执行get_or_create时,可能都在第一阶段SELECT查询不到记录,同时进入INSERT阶段,第一个请求写入成功,第二个请求写入时就会触发唯一约束校验失败,Django默认不会在写入失败后自动重试查询,会直接抛出异常。
修复建议
  • 调整get_or_create的传参,把不属于唯一约束的user字段放到defaults中:
action_history, action_added = ActionModel.objects.get_or_create(
    date=date_obj,
    account_name=unique_name,
    target=follower_obj,
    defaults={
        'identifier': history['user_id'],
        'user': user
    }
)
  • 增加异常捕获处理兼容并发场景:
from django.db import IntegrityError

try:
    action_history, action_added = ActionModel.objects.get_or_create(
        date=date_obj,
        account_name=unique_name,
        target=follower_obj,
        defaults={
            'identifier': history['user_id'],
            'user': user
        }
    )
except IntegrityError:
    # 并发写入冲突,重新查询已存在的记录
    action_history = ActionModel.objects.get(
        date=date_obj,
        account_name=unique_name,
        target=follower_obj,
    )
    action_added = False

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.09 06:12:01