1

我们有一个 django rest 框架 (DRF) 项目,它应该有多个数据库 (mongoDB)。每个数据库应该是独立的。我们能够连接到一个数据库,但是当我们要去另一个数据库进行写入连接时,正在发生连接,但数据存储在第一个连接的数据库中。我们更改了默认数据库和所有内容,但没有更改。

(注意:解决方案应该适合使用序列化器。因为我们需要在 DRF-mongoengine 中使用 DynamicDocumentSerializer。

提前致谢。

4

2 回答 2

0

我想,我终于得到了你需要的东西。

您可以做的是编写一个非常简单的中间件,将您的 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模块。

于 2019-02-20T10:37:49.100 回答
0

运行时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'}
于 2019-02-19T12:16:42.173 回答