我们有一个 django rest 框架 (DRF) 项目,它应该有多个数据库 (mongoDB)。每个数据库应该是独立的。我们能够连接到一个数据库,但是当我们要去另一个数据库进行写入连接时,正在发生连接,但数据存储在第一个连接的数据库中。我们更改了默认数据库和所有内容,但没有更改。
(注意:解决方案应该适合使用序列化器。因为我们需要在 DRF-mongoengine 中使用 DynamicDocumentSerializer。
提前致谢。
我们有一个 django rest 框架 (DRF) 项目,它应该有多个数据库 (mongoDB)。每个数据库应该是独立的。我们能够连接到一个数据库,但是当我们要去另一个数据库进行写入连接时,正在发生连接,但数据存储在第一个连接的数据库中。我们更改了默认数据库和所有内容,但没有更改。
(注意:解决方案应该适合使用序列化器。因为我们需要在 DRF-mongoengine 中使用 DynamicDocumentSerializer。
提前致谢。
我想,我终于得到了你需要的东西。
您可以做的是编写一个非常简单的中间件,将您的 url 模式映射到数据库:
from mongoengine import *
class DBSwitchMiddleware:
"""
This middleware is supposed to switch the database depending on request URL.
"""
def __init__(self, get_response):
# list all the mongoengine Documents in your project
import models
self.documents = [item for in dir(models) if isinstance(item, Document)]
def __call__(self, request):
# depending on the URL, switch documents to appropriate database
if request.path.startswith('/main/project1'):
for document in self.documents:
document.cls._meta['db_alias'] = 'db1'
elif request.path.startswith('/main/project2'):
for document in self.documents:
document.cls._meta['db_alias'] = 'db2'
# delegate handling the rest of response to your views
response = get_response(request)
return response
请注意,此解决方案可能容易出现竞争条件。我们在此处全局修改 Documents,因此如果启动了一个请求,然后在其执行过程中,第二个请求由同一个 python 解释器处理,它将覆盖document.cls._meta['db_alias']
设置,第一个请求将开始写入同一个数据库,这会严重破坏你的数据库。
如果您使用多线程,则 2 个请求处理程序使用相同的 python 解释器。因此,使用此解决方案,您不能使用多个线程启动服务器,而只能使用多个进程。
要解决线程问题,您可以使用threading.local()。如果您更喜欢上下文管理器方法,还有一个contextvars模块。
运行时connect()
只需为每个数据库分配一个别名,然后为每个 Document 指定一个指向特定数据库别名的db_alias参数:meta
settings.py
:
from mongoengine import connect
connect(
alias='user-db',
db='test',
username='user',
password='12345',
host='mongodb://admin:qwerty@localhost/production'
)
connect(
alias='book-db'
db='test',
username='user',
password='12345',
host='mongodb://admin:qwerty@localhost/production'
)
models.py
:
from mongoengine import Document
class User(Document):
name = StringField()
meta = {'db_alias': 'user-db'}
class Book(Document):
name = StringField()
meta = {'db_alias': 'book-db'}