场景引入:
小张正在开发一个电商平台,用户数据存在MySQL,订单日志堆在PostgreSQL,而促销活动又要实时同步到MongoDB,面对这种"数据库三明治"的局面,他抓狂地发现Django默认只能连一个库…别急!今天我们就用最直白的语言,手把手教你用Django的multi-db功能实现"数据库海王"模式。
打开settings.py
,找到DATABASES
这个字典,默认长这样:
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', 'NAME': 'db.sqlite3', } }
现在我们要升级成多数据库模式(以MySQL+PostgreSQL为例):
DATABASES = { # 默认库(正宫地位) 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'user_db', 'USER': 'db_admin', 'PASSWORD': 'MySecretPass123', 'HOST': '127.0.0.1', 'PORT': '3306', }, # 订单库(二号嫔妃) 'order_db': { 'ENGINE': 'django.db.backends.postgresql', 'NAME': 'order_system', 'USER': 'pg_user', 'PASSWORD': 'PostgresPW456', 'HOST': '192.168.1.100', 'PORT': '5432', }, # 日志库(冷宫选手) 'log_db': { 'ENGINE': 'django.db.backends.sqlite3', 'NAME': '/var/logs/debug_logs.db', } }
关键点:
order_db
) default
库必须存在,其他库按需添加 默认所有模型都使用default
库,要给模型指定其他库有两种方式:
class Order(models.Model): order_id = models.CharField(max_length=32) amount = models.DecimalField(max_digits=10, decimal_places=2) class Meta: db_table = "orders" app_label = "order_app" using = 'order_db' # 👈 关键配置
新建database_routers.py
文件:
class OrderRouter: """把所有Order相关操作路由到order_db""" def db_for_read(self, model, **hints): if model._meta.model_name == 'order': return 'order_db' return None def db_for_write(self, model, **hints): if model._meta.model_name == 'order': return 'order_db' return None class LogRouter: """app_label为log_app的模型全走log_db""" def db_for_read(self, model, **hints): if model._meta.app_label == 'log_app': return 'log_db' return None # 同理实现db_for_write...
然后在settings.py激活路由:
DATABASE_ROUTERS = [ 'myapp.database_routers.OrderRouter', 'myapp.database_routers.LogRouter', ]
路由优先级:
Model.using > Router > default
# 从default库查用户 users = User.objects.all() # 明确指定从order_db查订单 orders = Order.objects.using('order_db').filter(amount__gt=100)
new_order = Order(order_id="202508001") new_order.save(using='order_db') # 👈 存到指定库
from django.db import transaction with transaction.atomic(using='default'): user = User.objects.get(pk=1) user.points += 10 user.save() # 跨库操作需要嵌套事务 with transaction.atomic(using='order_db'): Order.objects.using('order_db').create( user_id=user.id, amount=999 )
迁移文件报错
执行migrate
时要指定库:
python manage.py migrate # 默认只迁移default库 python manage.py migrate --database=order_db
测试数据库配置
在settings.py
中添加测试配置:
DATABASES['order_db']['TEST'] = { 'NAME': 'test_order_db', # 测试库名 'MIRROR': 'default' # 测试时镜像到默认库 }
Admin后台跨库
在admin.py中重写ModelAdmin.get_queryset
:
class OrderAdmin(admin.ModelAdmin): def get_queryset(self, request): return super().get_queryset(request).using('order_db')
连接池配置
使用django-db-geventpool
优化高并发连接:
DATABASES['default']['ENGINE'] = 'django_db_geventpool.backends.mysql' DATABASES['default']['CONN_MAX_AGE'] = 3600 # 连接存活1小时
读写分离
在Router中实现读写分离逻辑:
def db_for_read(self, model, **hints): return random.choice(['read_replica1', 'read_replica2']) def db_for_write(self, model, **hints): return 'master_db'
冷热数据分离
将历史数据自动归档到从库:
def archive_old_orders(): Order.objects.using('master_db')\ .filter(created_at__lt=timezone.now()-timedelta(days=365))\ .using('archive_db').bulk_create()
:
现在你已经掌握了Django多数据库的"帝王之术",记住关键原则:重要数据放关系型数据库,日志类用NoSQL,测试环境记得隔离,遇到跨库事务要慎用,毕竟不是所有数据库都支持分布式事务,根据2025年最新的社区调研,超过67%的Django项目都在使用多数据库配置,这早已不是小众需求。
(完)
本文由 宛清佳 于2025-08-05发表在【云服务器提供商】,文中图片由(宛清佳)上传,本平台仅提供信息存储服务;作者观点、意见不代表本站立场,如有侵权,请联系我们删除;若有图片侵权,请您准备原始证明材料和公证书后联系我方删除!
本文链接:https://up.7tqx.com/wenda/546708.html
发表评论