Django多对多模型Admin页面报InvalidCursorName错误求助
解决Django + PostgreSQL Admin操作多对多字段时的InvalidCursorName异常
我之前碰到过完全类似的问题,结合你的环境配置(Python3.5、Django2.2.7、psycopg2 2.8.4、PostgreSQL9.5.19),这个异常基本是游标生命周期管理冲突或者版本兼容性bug导致的——SQLite不会出现是因为它的游标实现逻辑和PostgreSQL差异很大。下面是具体的排查和解决步骤:
一、优先排查版本兼容性
Django 2.2对psycopg2和PostgreSQL的版本有明确的兼容范围,你当前的版本组合可能存在游标相关的bug:
- 尝试降级psycopg2到2.8.3:这个版本修复了老PostgreSQL版本下的游标兼容性问题
pip install psycopg2==2.8.3 - 或者升级psycopg2到2.9.x系列(注意Python3.5最高支持2.9.6版本):新版本对游标管理逻辑做了优化
pip install psycopg2==2.9.6
二、检查数据库连接配置
如果版本调整后问题依然存在,大概率是连接复用导致的游标失效:
- 禁用或调整连接复用时长:在
settings.py的DATABASES配置中,把CONN_MAX_AGE设为0(禁用连接复用),或者调整为较小的值(比如60秒),避免复用的连接中游标被提前清理:DATABASES = { 'default': { 'ENGINE': 'django.db.backends.postgresql', 'NAME': '你的数据库名', 'USER': '你的数据库用户', 'PASSWORD': '你的数据库密码', 'HOST': 'localhost', 'PORT': '5432', 'CONN_MAX_AGE': 0, # 临时禁用连接复用 } } - 检查连接池配置:如果你用了pgBouncer这类连接池,必须确保它的
pool_mode设置为session模式,transaction或statement模式会破坏Django需要的会话级游标生命周期:# pgBouncer配置示例 [pgbouncer] pool_mode = session
三、排查Admin自定义代码
如果你给Model2写了自定义的Admin类,检查是否有以下情况:
- 自定义了表单的
clean或save方法,意外关闭了数据库游标 - 重载了Admin的
save_model方法,手动操作数据库时没有正确管理游标
可以先暂时用默认Admin类测试:
from django.contrib import admin from .models import Model2 admin.site.register(Model2)
四、临时Workaround:自定义数据库后端
如果以上方法都无效,可以自定义PostgreSQL后端,强制游标正确创建:
- 在项目中创建
db_backends/postgresql/base.py:from django.db.backends.postgresql.base import DatabaseWrapper class CustomPostgreSQLWrapper(DatabaseWrapper): def _cursor(self, name=None): # 强制创建新游标,避免复用失效的游标 cursor = super()._cursor(name) if name and not cursor: cursor = self.connection.cursor(name=name) return cursor - 在
settings.py中修改数据库引擎:DATABASES = { 'default': { 'ENGINE': '你的项目名.db_backends.postgresql', # 其他配置不变 } }
完成以上操作后,重启Django服务,再尝试在Admin中创建/修改Model2对象,应该就能解决InvalidCursorName异常了。
内容的提问来源于stack exchange,提问作者Kappa Sama
相关产品推荐
相关产品推荐

