Django配置数据库,入门用SQLite,上线用MySQL或PostgreSQL
这句结论同时也是绝大多数Django项目从开发到生产的必经之路,坦白讲,Django的数据库配置并没有传说中那么复杂,但它确实有几个容易踩坑的细节,尤其是时区、字符集和连接池这三个老生常谈的问题,本文会直接用配置代码和实操步骤,带你走一遍完整的配置流程。
先从最基础的SQLite开始零成本启动Django项目
如果你只是本地学习或者写个个人小工具,SQLite是Django默认给你准备好的轻量级方案,它不需要安装任何数据库服务,数据就是一个文件,随项目走。
SQLite配置的默认样子
在项目目录下的settings.py里,你会看到默认的DATABASES配置块:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': BASE_DIR / 'db.sqlite3',
}
}
这行代码写完后,运行python manage.py migrate,Django会自动在当前目录创建db.sqlite3文件,并建好所有内置表,这个过程完全不需要你操心账号密码,也不需要开启任何端口。
SQLite的局限性在哪里
行业共识认为SQLite适合并发读写不高的场景,它的写入锁是全局的,多个用户同时写入时会出现database is locked的报错,如果你的网站上线后日均访问量预估超过几千,那么早点换掉SQLite是明智的选择,业内专家指出,Django官方文档也明确建议,生产环境优先考虑PostgreSQL。
切换到MySQLdjango配置mysql数据库连接参数详解
大多数企业级Django项目选择的是MySQL,毕竟国内运维生态里MySQL的经验积累最丰富,django配置mysql数据库连接其实就四个关键参数:ENGINE、NAME、USER、PASSWORD,外加一个可选的HOST和PORT。
安装数据库驱动
Python操作MySQL需要中间桥梁,Django 4.x和5.x版本官方推荐的是mysqlclient库:
pip install mysqlclient
如果你安装时遇到mysql_config not found的报错,说明系统缺了依赖库,Ubuntu/Debian下先执行sudo apt-get install libmysqlclient-dev,CentOS执行sudo yum install mysql-devel,然后再装驱动。
在settings.py里配置MySQL连接
替换掉SQLite配置块,写成这样:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'your_db_name',
'USER': 'your_username',
'PASSWORD': 'your_password',
'HOST': '127.0.0.1',
'PORT': '3306',
'OPTIONS': {
'charset': 'utf8mb4',
},
}
}
这里特别要提醒你:OPTIONS里的charset务必写成utf8mb4,它能存储emoji和一些生僻汉字,普通utf8在插入特殊表情符号时会直接报Incorrect string value错误,据统计,这个报错是新手在django配置mysql数据库连接时遇到最多的问题。

创建数据库并执行迁移
进入MySQL命令行,先创建数据库:
CREATE DATABASE your_db_name CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
然后回到Django项目根目录,依次执行:
python manage.py makemigrations python manage.py migrate
migrate命令结束后,你可以用python manage.py shell进入交互环境,输入下面的代码验证连接是否成功:
from django.db import connection
with connection.cursor() as cursor:
cursor.execute("SELECT VERSION()")
print(cursor.fetchone())
能输出MySQL版本号,说明你的django配置mysql数据库连接已经彻底打通了。
django用什么数据库好SQLite、MySQL和PostgreSQL的对比
这是开发者在选型阶段问得最多的问题,django用什么数据库好其实没有绝对标准,关键在于你的项目规模、部署环境和团队技术栈积累。
三款主流数据库的特点对照表
| 维度 | SQLite | MySQL | PostgreSQL |
|---|---|---|---|
| 部署成本 | 零配置 | 需要独立安装和运维 | 需要独立安装和运维 |
| 并发能力 | 弱,支持小流量 | 强,支持高并发 | 强,支持超高并发 |
| 数据类型 | 基础类型 | 常用类型 | 最丰富,支持JSON等 |
| 全文搜索 | 支持有限 | 支持但一般 | 内置强大全文索引 |
| 地理位置 | 需第三方 | 需第三方 | 内置PostGIS |
| 备份恢复 | 复制文件即可 | mysqldump工具 | pg_dump工具 |
| 学习曲线 | 无需学过 | 团队熟悉度最高 | 功能强大但生态略少 |
按场景选择数据库
- 极简个人博客、本地开发调试 → SQLite,后续迁移也方便,Django的ORM屏蔽了大部分差异。
- 中小型企业官网、内容管理系统、电商后台 → MySQL,网上踩坑案例多,出现问题好查解决方案。
- 地理位置查询、复杂分析报表、高数据完整性要求的金融类项目 → PostgreSQL,它在复杂查询和数据处理上有明显优势。
- 如果你正在求职或接外包,甲方明确要求用某种数据库,那直接按需求来,Django本身不锁定数据库,切换成本很低。
还有个现实的情况是:Django对PostgreSQL的支持其实比MySQL更完善,比如Django内置的ArrayField、JSONField这些字段类型只有PostgreSQL才能用,你如果从零开始,没有机房和团队的历史包袱,直接上PostgreSQL反而更顺。
django数据库迁移报错怎么办十大高频问题排查思路
从SQLite切换到MySQL,或者直接建一个新项目,迁移阶段经常出问题,我把多年来高频遇到的django数据库迁移报错汇总一下,给你一份排查清单。
常见报错现象与对应处理方式
- 报错
django.db.utils.OperationalError: (1366, "Incorrect string value"):数据库或表字符集不是utf8mb4
,需要修改库表的默认字符集。
- 报错
django.db.utils.ProgrammingError: (1146, "Table ... doesn't exist"):没有执行migrate,或者migrations目录里的迁移文件被误删。 - 报错
ImproperlyConfigured: Error loading MySQLdb module:没有安装mysqlclient,或者安装的驱动不兼容当前Python版本。 - 报错
ConnectionRefusedError: [Errno 111]:MySQL服务没有启动,或者HOST和PORT填写有误。 - 报错
django.db.utils.OperationalError: (1045, "Access denied"):USER和PASSWORD不正确,需要检查MySQL权限分配。 - 报错
AttributeError: 'str' object has no attribute 'decode':这在老版本Python2环境会出现,新项目基本不会遇到,遇到就升级Python。 - 迁移报错回滚时
Migration ... is applied before its dependency:数据库记录的表状态与迁移文件不一致,需要找到django_migrations表手动清理对应记录。
一条命令快速定位迁移问题
大多数情况下,先跑这条命令看SQL的输出,能直观发现问题来源:
python manage.py sqlmigrate 你的应用名 迁移文件编号
比如python manage.py sqlmigrate app01 0001_initial,它会打印出对应的原生SQL语句,你看一眼是字符集问题还是字段类型问题,通常比直接看报错日志更清晰。
生产环境里的进阶配置连接池、时区与自动重连
配置完成后,上线前还有一些参数值得你花时间调整,这些不是必需的,但生产环境的朋友普遍会关心。
使用django-db-connection-pool提升并发性能
在Django中写数据库操作时,默认情况下每次请求都会新建数据库连接,用完就关闭,高并发下性能不太理想,行业共识是引入连接池机制,把数据库连接复用起来,常用的库是django-db-connection-pool,配置方式也很简单:
pip install django-db-connection-pool
然后在settings.py里修改ENGINE为:
DATABASES = {
'default': {
'ENGINE': 'django_db_pool.backends.mysql',
'NAME': 'your_db_name',
'USER': 'your_username',
'PASSWORD': 'your_password',
'HOST': '127.0.0.1',
'PORT': '3306',
'POOL_OPTIONS': {
'POOL_SIZE': 10,
'MAX_OVERFLOW': 5,
'RECYCLE': 3600,
},
}
}
POOL_SIZE代表初始连接数,MAX_OVERFLOW代表当连接不够用时最多额外增加的连接数,RECYCLE指定连接的最长复用周期,单位是秒,这套配置跑下来,你的Django应用在高并发下数据库握手次数会大幅减少。
Django连接MySQL的时区配置陷阱
如果你发现插入数据库的时间跟本地实际时间差了好几个小时,通常是因为settings.py里没有开启时区支持,Django 4.x系列默认USE_TZ = True,但MySQL连接需要配合设置:
LANGUAGE_CODE = 'zh-hans' TIME_ZONE = 'Asia/Shanghai' USE_I18N = True USE_TZ = True
此时Django在存储DateTimeField时会强制转成UTC格式存库,展示时按TIME_ZONE转换,如果你希望直接存北京时间,把USE_TZ = False加上,但很多框架内置功能默认按照UTC时间计算,改掉后可能引发其他奇怪的问题,所以不太建议新手关掉时区。
自动重连机制解决MySQL超时断连
Django应用长时间运行后,有时会报MySQL server has gone away错误,这是MySQL服务器端wait_timeout默认8小时,空闲连接被服务端主动关闭了,常规解决思路是加一个CONN_MAX_AGE参数,让Django主动复用连接:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'your_db_name',
'USER': 'your_username',
'PASSWORD': 'your_password',
'HOST': '127.0.0.1',
'PORT': '3306',
'CONN_MAX_AGE': 60,
}
}
这里的CONN_MAX_AGE单位是秒,设置为60表示连接最长保留60秒,超过后关闭,然后配合MySQL连接复用相关的CONN_HEALTH_CHECKS参数,在每次复用连接前先检测一下连接是否还活着,双管齐下能极大地减少断连报错。
想用好django数据库配置,还要懂得看官方文档
Django的数据库配置远不止这些,这部分官方文档写得很详细,当你需要解决更复杂的问题时,我建议你直接翻阅Django官网的Databases章节,里面涵盖了多数据库路由(读写分离)、自定义数据库后端、执行原生SQL等多场景操作路径。
问题解答环节
Django配置MySQL后,为什么中文写入数据库变成乱码?
MySQL服务器、数据库、数据表以及Django连接四方的字符集都要统一成utf8mb4,检查my.cnf配置文件,确保character-set-server=utf8mb4和collation-server=utf8mb4_unicode_ci,改动配置文件后要重启MySQL服务,再查看MySQL中的show variables like 'character_set_%'确认所有字符集变量都是utf8mb4。
Django从SQLite切换到MySQL,原有数据怎么迁移?
推荐使用Django自带dumpdata和loaddata管理命令,在SQLite环境执行python manage.py dumpdata > data.json,然后修改settings.py的数据库配置切换到MySQL,执行python manage.py migrate建好空表,再执行python manage.py loaddata data.json,如果数据量比较大,可以使用第三方工具django-import-export,它能分批次导出导入,避免一次性读取大文件导致内存溢出。
使用django-db-connection-pool后并发性能提升明显吗?
对于频繁读写数据库的接口来说,引入连接池能有效减少建立TCP连接和权限验证的耗时,在并发数不高时可能看不出什么差距,但压测工具模拟几百个并发请求时,连接池版本比默认版本的吞吐量有非常可观的提升,需要提醒的是,连接池本身占用数据库连接数,务必同步调大MySQL的max_connections上限,否则连接池把连接耗尽后,其他服务反而连不上数据库了。

