Django 2.0.5处理含%符号列名时SQL字符串格式化报错求助
解决Django 2.0.5中列名含%符号导致的调试模式SQL格式化报错问题
这个问题是Django早期版本(比如你用的2.0.5)在调试模式下的一个已知bug:当数据库列名包含%时,Django在生成调试用的SQL字符串时,会把列名里的%误认为是字符串格式化占位符,从而触发ValueError。而且正如你发现的,这个问题只在DEBUG=True时出现——生产模式下Django不会执行这个有问题的SQL格式化输出,所以生产环境不会受影响。
下面是几个可行的解决方案,按推荐程度排序:
1. 升级Django版本(彻底解决)
这个问题已经在Django的后续版本中被修复了。如果你的项目兼容性允许,建议升级到Django 2.2 LTS或更高版本,这样就能从根本上解决这个问题,不需要任何临时补丁。升级前记得先在测试环境验证现有代码的兼容性。
2. 自定义SQLite操作类,修复调试SQL的格式化逻辑
如果暂时无法升级Django,我们可以重写SQLite的last_executed_query方法,避开%符号的冲突:
步骤1:创建自定义操作类
在你的项目中新建一个文件,比如yourapp/backends/sqlite3/operations.py,内容如下:
from django.db.backends.sqlite3.operations import DatabaseOperations class CustomSQLiteOperations(DatabaseOperations): def last_executed_query(self, cursor, sql, params): try: # 先尝试原方法,如果没问题就直接返回 return super().last_executed_query(cursor, sql, params) except (ValueError, TypeError): # 遇到格式化错误时,先把SQL中的%转义为%%,再执行格式化 escaped_sql = sql.replace('%', '%%') return escaped_sql % params
步骤2:配置使用自定义操作类
在项目的settings.py中修改数据库配置,指定自定义的操作类:
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', 'NAME': BASE_DIR / 'db.sqlite3', 'OPTIONS': { 'operations_class': 'yourapp.backends.sqlite3.operations.CustomSQLiteOperations', }, } }
这样调试时,Django会用我们修改后的方法处理SQL格式化,避免列名中的%引发报错。
3. 临时调试规避方案
如果你只是临时需要调试功能,可以暂时把settings.py中的DEBUG设为False,这样Django不会执行那个触发报错的SQL格式化操作,就能正常运行代码了。当然这个方案只适合临时调试,开发时会失去Django的调试工具支持,所以不推荐长期使用。
内容的提问来源于stack exchange,提问作者Utkarsh Agarwal
相关产品推荐
相关产品推荐

