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

在Django中使用CrateDB作为时序数据库遇兼容性及函数报错问题

问题

在Docker环境下尝试将CrateDB作为Django的时序数据库使用,初始部署版本:

  • Django: 4.1.3
  • CrateDB: 5.1.0

出现兼容性错误:

django.db.utils.NotSupportedError: PostgreSQL 11 or later is required (found 10.5)

将Django降级至3.0后,兼容性错误消失,但出现新的内部错误:

System check identified no issues (0 silenced).
Exception in thread django-main-thread:
Traceback (most recent call last):
  File "/usr/local/lib/python3.9/site-packages/django/db/backends/utils.py", line 82, in _execute
    return self.cursor.execute(sql)
psycopg2.errors.InternalError_: Unknown function: pg_catalog.pg_table_is_visible(c.oid)
CONTEXT:  io.crate.exceptions.SQLExceptions.esToCrateException(SQLExceptions.java:164)
io.crate.exceptions.SQLExceptions.prepareForClientTransmission(SQLExceptions.java:151)
io.crate.protocols.postgres.Messages.sendErrorResponse(Messages.java:190)
io.crate.protocols.postgres.PostgresWireProtocol.handleSingleQuery(PostgresWireProtocol.java:795)
io.crate.protocols.postgres.PostgresWireProtocol.lambda$handleSimpleQuery$3(PostgresWireProtocol.java:748)
java.base/java.util.concurrent.CompletableFuture.uniComposeStage(CompletableFuture.java:1187)
java.base/java.util.concurrent.CompletableFuture.thenCompose(CompletableFuture.java:2309)
io.crate.protocols.postgres.PostgresWireProtocol.handleSimpleQuery(PostgresWireProtocol.java:748)
io.crate.protocols.postgres.PostgresWireProtocol$MessageHandler.dispatchMessage(PostgresWireProtocol.java:335)
io.crate.protocols.postgres.PostgresWireProtocol$MessageHandler.dispatchState(PostgresWireProtocol.java:325)
io.crate.protocols.postgres.PostgresWireProtocol$MessageHandler.channelRead0(PostgresWireProtocol.java:293)
io.crate.protocols.postgres.PostgresWireProtocol$MessageHandler.channelRead0(PostgresWireProtocol.java:277)
io.netty.channel.SimpleChannelInboundHandler.channelRead(SimpleChannelInboundHandler.java:99)
io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:336)
io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:308)
io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)



The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/usr/local/lib/python3.9/threading.py", line 980, in _bootstrap_inner
    self.run()
  File "/usr/local/lib/python3.9/threading.py", line 917, in run
    self._target(*self._args, **self._kwargs)
  File "/usr/local/lib/python3.9/site-packages/django/utils/autoreload.py", line 64, in wrapper
    fn(*args, **kwargs)
  File "/usr/local/lib/python3.9/site-packages/django/core/management/commands/runserver.py", line 121, in inner_run
    self.check_migrations()
  File "/usr/local/lib/python3.9/site-packages/django/core/management/base.py", line 486, in check_migrations
    executor = MigrationExecutor(connections[DEFAULT_DB_ALIAS])
  File "/usr/local/lib/python3.9/site-packages/django/db/migrations/executor.py", line 18, in __init__
    self.loader = MigrationLoader(self.connection)
  File "/usr/local/lib/python3.9/site-packages/django/db/migrations/loader.py", line 53, in __init__
    self.build_graph()
  File "/usr/local/lib/python3.9/site-packages/django/db/migrations/loader.py", line 220, in build_graph
    self.applied_migrations = recorder.applied_migrations()
  File "/usr/local/lib/python3.9/site-packages/django/db/migrations/recorder.py", line 77, in applied_migrations
    if self.has_table():
  File "/usr/local/lib/python3.9/site-packages/django/db/migrations/recorder.py", line 56, in has_table
    tables = self.connection.introspection.table_names(cursor)
  File "/usr/local/lib/python3.9/site-packages/django/db/backends/base/introspection.py", line 52, in table_names
    return get_names(cursor)
  File "/usr/local/lib/python3.9/site-packages/django/db/backends/base/introspection.py", line 47, in get_names
    return sorted(ti.name for ti in self.get_table_list(cursor)
  File "/usr/local/lib/python3.9/site-packages/django/db/backends/postgresql/introspection.py", line 49, in get_table_list
    cursor.execute("""
  File "/usr/local/lib/python3.9/site-packages/django/db/backends/utils.py", line 98, in execute
    return super().execute(sql, params)
  File "/usr/local/lib/python3.9/site-packages/django/db/backends/utils.py", line 66, in execute
    return self._execute_with_wrappers(sql, params, many=False, executor=self._execute)
  File "/usr/local/lib/python3.9/site-packages/django/db/backends/utils.py", line 75, in _execute_with_wrappers
    return executor(sql, params, many, context)
  File "/usr/local/lib/python3.9/site-packages/django/db/backends/utils.py", line 84, in _execute
    return self.cursor.execute(sql, params)
  File "/usr/local/lib/python3.9/site-packages/django/db/utils.py", line 90, in __exit__
    raise dj_exc_value.with_traceback(traceback) from exc_value
  File "/usr/local/lib/python3.9/site-packages/django/db/backends/utils.py", line 82, in _execute
    return self.cursor.execute(sql)
django.db.utils.InternalError: Unknown function: pg_catalog.pg_table_is_visible(c.oid)
CONTEXT:  io.crate.exceptions.SQLExceptions.esToCrateException(SQLExceptions.java:164)
io.crate.exceptions.SQLExceptions.prepareForClientTransmission(SQLExceptions.java:151)
io.crate.protocols.postgres.Messages.sendErrorResponse(Messages.java:190)
io.crate.protocols.postgres.PostgresWireProtocol.handleSingleQuery(PostgresWireProtocol.java:795)
io.crate.protocols.postgres.PostgresWireProtocol.lambda$handleSimpleQuery$3(PostgresWireProtocol.java:748)
java.base/java.util.concurrent.CompletableFuture.uniComposeStage(CompletableFuture.java:1187)
java.base/java.util.concurrent.CompletableFuture.thenCompose(CompletableFuture.java:2309)
io.crate.protocols.postgres.PostgresWireProtocol.handleSimpleQuery(PostgresWireProtocol.java:748)
io.crate.protocols.postgres.PostgresWireProtocol$MessageHandler.dispatchMessage(PostgresWireProtocol.java:335)
io.crate.protocols.postgres.PostgresWireProtocol$MessageHandler.dispatchState(PostgresWireProtocol.java:325)
io.crate.protocols.postgres.PostgresWireProtocol$MessageHandler.channelRead0(PostgresWireProtocol.java:293)
io.crate.protocols.postgres.PostgresWireProtocol$MessageHandler.channelRead0(PostgresWireProtocol.java:277)
io.netty.channel.SimpleChannelInboundHandler.channelRead(SimpleChannelInboundHandler.java:99)
io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:336)
io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:308)
io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)

解决建议

  • 使用CrateDB官方适配的Django后端
    不要直接用PostgreSQL后端连接CrateDB,CrateDB提供了专门的Django数据库后端django-crate,安装后配置数据库引擎为crate,能避免PostgreSQL特有的函数调用问题,比如pg_table_is_visible这类CrateDB不支持的PostgreSQL函数。

  • 调整Django与CrateDB版本匹配

    • 若坚持用PostgreSQL后端,需找版本兼容组合:CrateDB 5.x兼容PostgreSQL 10.x协议,所以Django版本不能要求PostgreSQL 11+,比如选Django 3.2.x(LTS版本),它对PostgreSQL的最低要求是9.6;同时需确认该版本Django的数据库自省逻辑是否依赖pg_table_is_visible,若仍依赖则需自定义自省类覆盖相关方法。
    • 升级CrateDB到5.3+版本,部分高版本可能增加了对更多PostgreSQL函数的支持,需参考官方文档确认兼容说明。
  • 自定义数据库自省类
    针对Django 3.0的PostgreSQL自省调用pg_table_is_visible的问题,可自定义自省类重写get_table_list方法,移除对该函数的调用:

from django.db.backends.postgresql.introspection import DatabaseIntrospection

class CrateDBIntrospection(DatabaseIntrospection):
    def get_table_list(self, cursor):
        # 重写方法,移除pg_table_is_visible调用
        cursor.execute("""
            SELECT c.relname, CASE WHEN c.relkind = 'v' THEN 'v' ELSE 't' END AS table_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', 'm')
              AND n.nspname NOT IN ('pg_catalog', 'pg_toast')
              AND n.nspname !~ '^pg_temp_'
        """)
        return [self.TableInfo(row[0], row[1]) for row in cursor.fetchall()]

然后在数据库配置中指定该自省类:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': 'your_db',
        'USER': 'crate',
        'PASSWORD': '',
        'HOST': 'crate-db',
        'PORT': '5432',
        'OPTIONS': {
            'introspection_class': 'your_app.path.to.CrateDBIntrospection',
        },
    }
}
  • 禁用Django迁移检查(临时方案)
    开发阶段临时测试可跳过迁移检查,启动命令添加--skip-checks参数:
python manage.py runserver --skip-checks

注意该方案不适合生产环境。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 17:10:24