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

重写Django Postgres数据库Wrapper设置search_path触发错误

Django连接PostgreSQL Schema时Admin页面报错的原因及解决方案

问题原因

你覆写_cursor方法时未考虑服务器端游标的场景。当Django处理大量数据(比如Admin详情页的关联数据查询)时,会创建带name参数的服务器端游标,此时PostgreSQL的游标声明语法为DECLARE [cursor_name] NO SCROLL CURSOR WITH HOLD FOR [查询语句]。你的代码在获取游标后立即执行SET search_path,导致Django将两个语句拼接成一条无效SQL,触发语法错误。

解决方案

不要在_cursor方法中执行SET语句,改用以下两种可靠方式:

方式一:覆写init_connection_state方法

该方法是Django在每次新连接建立完成后调用的初始化逻辑,每个连接仅执行一次,不会与游标操作冲突:

from django.db.backends.postgresql.base import DatabaseWrapper

class CustomDatabaseWrapper(DatabaseWrapper):
    def init_connection_state(self):
        super().init_connection_state()
        # 使用self.cursor()获取普通游标,不会触发服务器端游标逻辑
        with self.cursor() as cursor:
            cursor.execute('SET search_path = schema_name')

方式二:使用connection_created信号

在项目的apps.py或初始化文件中注册信号,在连接建立后自动执行SET:

from django.db.backends.signals import connection_created
from django.dispatch import receiver

@receiver(connection_created)
def set_search_path(sender, connection, **kwargs):
    # 仅针对PostgreSQL连接执行
    if connection.vendor == 'postgresql':
        with connection.cursor() as cursor:
            cursor.execute('SET search_path = schema_name')

注意事项

  • 将代码中的schema_name替换为实际需要的Schema名称,多个Schema可用逗号分隔,例如SET search_path = schema1, schema2, public
  • 两种方式均可避开服务器端游标拼接SQL的问题,同时保证每个新连接都正确设置search_path

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 16:00:59