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

Python中指定主键后使用Peewee ORM插入数据失败的问题求助

解决Peewee设置code为主键后无法插入数据的问题

先定位错误原因

你的异常捕获太宽泛,只打印"aa"根本看不到具体错误。先修改代码,打印详细异常信息,才能精准定位问题:

for data in corp_list._stock_codes:
    idx = corp_list._stock_codes.get(data)
    info = corp_list[idx].info
    stock = Stock(
        name=info.get("corp_name"),
        code=info.get("stock_code"),
        sector=info.get("sector"),
        product=info.get("product"),
        corp_code=info.get("corp_code"),
        corp_cls=info.get("corp_cls"),
    )
    try:
        stock.save()
    except Exception as e:
        print(f"插入失败: {str(e)}, 对应数据: {info}")

常见问题及解决方法

1. stock_code为空或None

主键字段不允许为NULL,如果info.get("stock_code")返回空值,插入会直接失败。解决方法:插入前过滤掉无stock_code的数据:

for data in corp_list._stock_codes:
    idx = corp_list._stock_codes.get(data)
    info = corp_list[idx].info
    stock_code = info.get("stock_code")
    # 过滤空的stock_code
    if not stock_code:
        print(f"缺少股票代码,跳过数据: {info}")
        continue
    stock = Stock(
        name=info.get("corp_name"),
        code=stock_code,
        sector=info.get("sector"),
        product=info.get("product"),
        corp_code=info.get("corp_code"),
        corp_cls=info.get("corp_cls"),
    )
    try:
        stock.save()
    except Exception as e:
        print(f"插入失败: {str(e)}, 对应数据: {info}")

2. 数据库中已存在相同code的记录

主键必须唯一,如果重复插入相同code的数据,会触发唯一约束错误。可以用两种方式处理:

方式一:用get_or_create(存在则获取,不存在则插入)

for data in corp_list._stock_codes:
    idx = corp_list._stock_codes.get(data)
    info = corp_list[idx].info
    stock_code = info.get("stock_code")
    if not stock_code:
        print(f"缺少股票代码,跳过数据: {info}")
        continue
    # 尝试获取或创建,defaults里是除主键外的字段
    stock, created = Stock.get_or_create(
        code=stock_code,
        defaults={
            "name": info.get("corp_name"),
            "sector": info.get("sector"),
            "product": info.get("product"),
            "corp_code": info.get("corp_code"),
            "corp_cls": info.get("corp_cls"),
        }
    )
    # 如果记录已存在,可选择更新字段
    if not created:
        stock.name = info.get("corp_name")
        stock.sector = info.get("sector")
        stock.product = info.get("product")
        stock.corp_code = info.get("corp_code")
        stock.corp_cls = info.get("corp_cls")
        stock.save()

方式二:用PostgreSQL的Upsert(效率更高)

因为你用的是PostgreSQL,Peewee支持直接用on_conflict实现更新插入:

for data in corp_list._stock_codes:
    idx = corp_list._stock_codes.get(data)
    info = corp_list[idx].info
    stock_code = info.get("stock_code")
    if not stock_code:
        print(f"缺少股票代码,跳过数据: {info}")
        continue
    # 插入或更新
    Stock.insert(
        name=info.get("corp_name"),
        code=stock_code,
        sector=info.get("sector"),
        product=info.get("product"),
        corp_code=info.get("corp_code"),
        corp_cls=info.get("corp_cls"),
    ).on_conflict(
        conflict_target=[Stock.code],  # 冲突字段是主键code
        # 冲突时更新这些字段
        preserve=[Stock.name, Stock.sector, Stock.product, Stock.corp_code, Stock.corp_cls]
    ).execute()

3. 数据库表结构未更新

修改模型(把code设为主键)后,如果没有重新生成表结构,原来的表可能还保留自动生成的id主键,或者code字段不是主键,导致插入失败。测试环境下可以直接重建表(注意:会清空原有数据):

# 先删除旧表
pg_db.drop_tables([Stock])
# 创建新表
pg_db.create_tables([Stock])

生产环境建议用peewee-migrate迁移工具修改表结构,避免数据丢失。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 03:08:30