PythonAnywhere上Django从SQLite迁移MySQL遇Specified key was too long错误
嘿,这个问题我之前帮好几个开发者踩过坑!虽然你的Showww模型看起来超简单,但这个错误其实大多和Django默认的数据库配置、以及MySQL InnoDB的索引长度限制有关——别慌,咱们一步步来搞定它:
核心原因
MySQL的InnoDB引擎默认对单个索引的长度限制是767字节。Django默认使用utf8mb4字符集(支持emoji等4字节字符),每个字符占4字节,算下来单个字段的索引最大只能是191字符(191×4=764,接近767)。如果你的项目里有默认应用(比如django.contrib.auth)的字段长度超过这个值,或者联合索引总长度超标,就会触发这个错误。
解决方案(按简易程度排序)
方案1:切换为utf8字符集(最快解决)
如果你的项目不需要支持emoji等4字节字符,直接修改settings.py里的数据库配置,指定使用utf8字符集(每个字符3字节,767÷3≈255,刚好覆盖Django默认的varchar(255)字段):
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': '你的数据库名', 'USER': '你的数据库用户名', 'PASSWORD': '你的数据库密码', 'HOST': 'PythonAnywhere提供的MySQL主机', 'PORT': '3306', 'OPTIONS': { 'charset': 'utf8', 'use_unicode': True, }, } }
修改后,执行以下步骤重新迁移:
- 删除应用目录下
migrations文件夹中除__init__.py外的所有文件 - 运行
python manage.py makemigrations - 运行
python manage.py migrate
方案2:保留utf8mb4并开启大索引支持
如果必须使用utf8mb4(比如要支持emoji),需要开启InnoDB的大前缀支持。在settings.py的数据库配置中添加初始化命令:
DATABASES = { 'default': { # 其他配置不变 'OPTIONS': { 'charset': 'utf8mb4', 'use_unicode': True, 'init_command': "SET sql_mode='STRICT_TRANS_TABLES', innodb_strict_mode=1, innodb_file_format=Barracuda, innodb_file_per_table=1, innodb_large_prefix=1", }, } }
这会在每次连接数据库时自动开启大索引支持,把单个索引的长度限制提升到3072字节,足够容纳utf8mb4的长字段。之后同样重新执行迁移步骤即可。
方案3:手动调整字段索引长度
如果以上方案都不行,你可以针对触发错误的字段(比如默认应用里的username等)手动限制长度。比如修改django.contrib.auth的User模型(或者自定义用户模型),把username的max_length设为191:
from django.contrib.auth.models import AbstractUser class CustomUser(AbstractUser): username = models.CharField(max_length=191, unique=True)
然后在settings.py中指定自定义用户模型:
AUTH_USER_MODEL = 'yourapp.CustomUser'
这种方法比较繁琐,仅推荐前两种方案无效时使用。
内容的提问来源于stack exchange,提问作者gpanterov

