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

Django批量导入用户创建Profile时报错Field 'id' expected a number but got nan

问题原因与修复方案

报错根因

  • Pandas读取CSV时空单元格会默认转换为NaN类型,你直接将row['company_id']、row['app_id']赋值给Profile外键字段时,外键需要接收数字或None值,NaN不属于合法值,触发Field 'id' expected a number but got nan报错。
  • 你在循环阶段将尚未入库的User实例提前绑定给Profile,User执行bulk_create后才会生成数据库id,但之前存入profiles列表的Profile关联的仍是无id的旧User实例,入库时user外键也会触发同类id不合法错误。

具体修复方法

修复思路:首先统一处理CSV读取的NaN为合法的None值,其次等User批量入库生成id后,再组装Profile实例入库。
修复后代码如下:

import pandas as pd
import io
from django.contrib.auth.hashers import make_password
import logging

LOGGER = logging.getLogger(__name__)

def import_users(csv_file):
    # 读取CSV时关闭默认NaN转换,避免空值转NaN
    df = pd.read_csv(io.StringIO(csv_file.decode('utf-8')), keep_default_na=False)
    users = []
    # 暂存每行对应的Profile参数,不提前创建实例
    profile_params_list = []

    for index, row in df.iterrows():
        user = User(
            username=row['username'],
            password=make_password(str(row['password'])),
            first_name=row['firstname'],
            last_name=row['lastname'],
            is_active=True,
            email=row.get('email') or None
        )
        users.append(user)

        # 处理Profile参数,空值转None
        profile_params = {}
        # company允许为null,空值直接转None
        if pd.notna(row['company_id']):
            profile_params['company_id'] = row['company_id']
        else:
            profile_params['company_id'] = None
        # app字段非空有默认值,只有当app_id非空时才赋值,否则走模型默认值
        if pd.notna(row['app_id']):
            profile_params['app_id'] = row['app_id']
        profile_params_list.append(profile_params)

    # 批量创建User,生成数据库id
    try:
        users = User.objects.bulk_create(users, ignore_conflicts=False)
    except Exception as e:
        LOGGER.exception(f"用户批量创建失败: {str(e)}")
        return

    # 绑定已生成id的User实例,组装Profile列表
    profiles = []
    for user, profile_params in zip(users, profile_params_list):
        profiles.append(Profile(user=user, **profile_params))

    # 批量创建Profile
    try:
        Profile.objects.bulk_create(profiles, ignore_conflicts=False)
    except Exception as e:
        LOGGER.exception(f"Profile批量创建失败: {str(e)}")

额外注意事项

  • 若业务要求company_id必须传值,可在参数处理阶段增加校验,空值直接跳过该行或者抛出错误提示,避免入库空的关联公司。
  • 若CSV中app_id字段保证所有行都有合法值,不需要走模型默认值,可直接按company_id的逻辑处理转换即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 16:30:05