Django使用import-export导入Excel到MySQL时报date列非空约束错误
导入报错的原因定位与修复步骤
核心问题排查逻辑
你遇到的(1048, "Column 'date' cannot be null")报错,本质是导入时所有数据行的date字段都没有获取到有效值,被设为null后触发了MySQL的非空约束,对应代码里的问题按优先级排序如下:
- pandas读取Excel的表头索引设置错误
pd.read_excel()的header参数是从0开始计数的,代表把Excel物理位置的第几行作为列名。你现在传了header=1,相当于把Excel第二行(也就是第一行实际数据2020-1-1、26.5...)当成了列名。这种情况下转成Dataset后,根本不存在对应模型date字段的列,自然所有行的date值都是null。
修复方式:把参数改成header=0,正确读取第一行的Date、Salt...作为列名。 - 列名大小写不匹配
你的Excel列名是首字母大写的Date,但模型里定义的字段名是全小写的date。即使修正了表头读取的问题,import-export默认是按列名和模型字段名完全匹配做映射的,不修正大小写还是会出现字段值为null的问题。
修复方式:读表后统一把列名转成小写,加一行代码即可:df.columns = df.columns.str.lower() - 变量名拼写错误
你在定义资源实例时写的是products_resource = ProductsResource()(带s),但调用导入逻辑时写的是result = product_resource.import_data(...)(不带s)。这种笔误轻则直接触发NameError中断程序,重则如果环境中有同名全局变量,会完全打乱导入逻辑。
修复方式:统一变量名,去掉拼写错误。 - 预校验逻辑的漏洞
你虽然开了dry_run=True的测试模式和raise_errors=True的错误抛出开关,但当列和模型字段完全匹配不上时,import-export只会把缺失值默认为None,这种内存层面的模拟操作不会触发MySQL的非空约束检查,导致你以为测试环节没有问题,直到真正写库时才触发报错。
修复方式:测试环节打印Dataset的列名和导入错误详情,确认列名和模型字段完全对应后,再执行正式导入。
修复后的核心代码示例
def dataimport(): products_resource = ProductsResource() dataset = Dataset() dirname = Path(__file__).resolve().parent.parent file_name = 'Price.xlsx' file_location = os.path.join(dirname, file_name) # 修正header参数,从第0行(第一行)读取表头 df = pd.read_excel(file_location, header=0, usecols='A:F') # 统一列名为小写,和模型字段名匹配 df.columns = df.columns.str.lower() dataset.load(df) result = products_resource.import_data(dataset, dry_run=True, raise_errors=True) # 打印测试结果和详细错误 print(f"导入测试是否存在错误: {result.has_errors()}") if result.has_errors(): for row_err in result.row_errors(): print(f"错误详情: {row_err}") # 无错误时才执行正式导入 if not result.has_errors(): products_resource.import_data(dataset, dry_run=False)
内容的提问来源于stack exchange,提问作者shashwata
相关产品推荐
相关产品推荐

