Django Docker部署生产库报错column c.relispartition不存在如何解决
问题根因
- 生产环境PostgreSQL版本低于10,
pg_class系统表不存在relispartition字段,该字段是PostgreSQL 10版本新增的分区表标识字段 - 你当前使用的Django版本≥3.2,该版本及以上的Django官方停止支持PostgreSQL 9.6及更早版本,内置的PostgreSQL内省查询逻辑固定会读取
relispartition字段,触发报错 - 本地PostgreSQL版本≥10,所以运行无异常
可行解决方案
方案1:降级Django版本(最快捷,无侵入)
如果生产PostgreSQL版本暂时无法升级,将Django版本降级到3.1.x,该版本仍支持PostgreSQL 9.6,不会触发relispartition字段查询逻辑。
修改requirements.txt中Django版本声明为:
Django~=3.1.14
重新构建Docker镜像即可生效,不需要修改业务代码,也不需要调整数据库。
方案2:补丁覆盖Django内置内省逻辑(无需降级Django,无需修改数据库)
如果必须使用当前高版本Django,可以通过猴子补丁覆盖PostgreSQL内省的get_table_list方法,移除对relispartition字段的引用:
- 在项目根目录新建
pg_patch.py文件,写入以下代码:
from django.db.backends.postgresql.introspection import DatabaseIntrospection from django.db.backends.base.introspection import TableInfo original_get_table_list = DatabaseIntrospection.get_table_list def patched_get_table_list(self, cursor): cursor.execute(""" SELECT c.relname, CASE WHEN c.relkind IN ('r', 'p') THEN 't' WHEN c.relkind = 'v' THEN 'v' ELSE 't' END AS type FROM pg_catalog.pg_class c LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace WHERE c.relkind IN ('r', 'v', 'p') AND n.nspname = (%s) """, [self.connection.schema_name]) return [ TableInfo(row[0], row[1]) for row in cursor.fetchall() ] DatabaseIntrospection.get_table_list = patched_get_table_list
- 在项目
manage.py的最顶部,导入模块的位置先导入这个补丁:
import pg_patch # 原有其他导入代码保持不变
重新构建镜像即可,不需要修改任何业务逻辑和数据库配置。
方案3:升级生产PostgreSQL版本(长期最优)
如果有升级数据库的操作空间,将生产PostgreSQL版本升级到10及以上,从根本上解决版本兼容性问题,不需要修改任何项目代码。
内容的提问来源于stack exchange,提问作者Magalhaes
相关产品推荐
相关产品推荐

