PostgreSQL批量导入CSV未使用默认值的问题排查
问题原因与解决方案
核心问题
Django模型中设置的default="NSW"是ORM层面的默认值,仅在通过Django代码(比如Localities.objects.create())创建对象时自动填充,不会同步到PostgreSQL数据库表的字段默认值中。当你直接使用PostgreSQL的\COPY命令(绕过Django ORM)导入数据时,数据库找不到该字段的默认值,就会给state列赋值为null,触发非空约束错误。
解决方案
方案1:同步数据库字段默认值
让PostgreSQL的state字段也带上默认值,这样\COPY导入时会自动使用该值:
- 确保Django模型
state字段已设置default="NSW"(你已完成此步骤)。 - 生成并执行新的迁移文件,将默认值同步到数据库:
执行完成后,数据库中python manage.py makemigrations python manage.py migratedatacollector_localities表的state字段会添加DEFAULT 'NSW'约束,之后再运行原\COPY命令即可正常导入。
方案2:导入时显式指定state值
如果不想修改数据库结构,可以通过临时表中转,手动给state赋值:
-- 创建临时表存储CSV数据 CREATE TEMP TABLE temp_localities (name text, postcode text); -- 导入CSV到临时表 \COPY temp_localities FROM '/postcodes-nsw.csv' DELIMITER ',' CSV HEADER; -- 将临时表数据插入目标表,同时指定state为NSW INSERT INTO datacollector_localities(name, postcode, state) SELECT name, postcode, 'NSW' FROM temp_localities; -- 删除临时表 DROP TABLE temp_localities;
也可以直接给CSV每行追加NSW后导入(依赖容器内安装sed工具,未安装可先执行apt-get install sed):
\COPY datacollector_localities(name, postcode, state) FROM PROGRAM 'cat /postcodes-nsw.csv | sed ''s/$/,NSW/'' ' DELIMITER ',' CSV HEADER;
方案3:通过Django ORM导入
使用Django的方式导入数据,让ORM自动处理默认值:
- 编写自定义Django管理命令,读取CSV文件并通过
Localities.objects.create(name=xxx, postcode=xxx)创建对象,此时Django会自动填充state为NSW。 - 或使用
django-import-export第三方库,配置导入规则后通过后台或命令行导入,同样会自动应用模型默认值。
内容的提问来源于stack exchange,提问作者tanbog
相关产品推荐
相关产品推荐

