Ubuntu部署Django执行migrate时遇OperationalError问题求助
问题根源与解决方案
嘿,这个问题我之前排查过类似的!本质是不同系统下SQLite对带特殊字符的表名解析规则不一致导致的,跟你用的Django版本也有关系。
为什么会出现这个奇怪的报错?
你给Order模型指定了db_table='xxx(S)',这里的括号()在SQL语法里是有特殊用途的(比如用来写函数调用、子查询)。
- 在你的macOS本地环境里,要么是SQLite版本比较新,要么是Django自动帮你把带特殊字符的表名用引号包裹起来了(比如生成的SQL是
CREATE TABLE "xxx(S)" (...)),SQLite会把整个"xxx(S)"当作完整表名,所以一切正常。 - 但在Ubuntu服务器上的Django 3.0.3/2.2.5版本中,Django没有正确转义这个带括号的表名,生成的SQL变成了
CREATE TABLE xxx(S) (...)。这时候SQLite会错误地把xxx当成表名,把(S)解析成SQL语法的一部分,进而出现找不到REFERRING.S列的诡异报错——其实这是SQL解析混乱后产生的错误提示,跟你模型里的字段完全没关系。
怎么解决?
给你两个可行的方案,推荐第一个:
- 彻底规避SQL特殊字符:直接修改
db_table的值,把括号这类特殊字符换成合法的命名,比如改成db_table='xxx_s'或者db_table='xxxs'。然后删除旧的迁移文件(除了__init__.py),重新执行python manage.py makemigrations和python manage.py migrate,这样不管在哪个系统上都能正常运行。 - 手动添加转义引号:如果一定要保留原有命名风格,可以把
db_table写成'"xxx(S)"'(注意是双引号嵌套在单引号里),这样Django生成SQL时会保留双引号,让SQLite正确识别整个表名。不过这个方法不推荐,因为不同数据库对引号的处理规则不一样,会影响跨数据库的兼容性。
验证方法
按照第一个方案修改后,重新生成迁移脚本,再执行migrate命令,应该就能顺利完成数据库迁移了,不会再出现那个莫名其妙的no such column报错。
内容的提问来源于stack exchange,提问作者Dingkun Liu
相关产品推荐
相关产品推荐

