Несколько mongoDB, связанных с одним и тем же django отдыхом рамочного проекта
У нас есть один проект django rest Framework (DRF), который должен иметь несколько баз данных (mongoDB). Каждая база данных должна быть независимой. Мы можем подключиться к одной базе данных, но когда мы собираемся в другую БД для записи, происходит соединение, но данные сохраняются в БД, которая сначала подключается. Мы изменили БД по умолчанию и все, но без изменений.
(Примечание: решение должно быть подходящим для использования сериализатора. Потому что нам нужно использовать DynamicDocumentSerializer в DRF-mongoengine.
Заранее спасибо.
2 ответа
Я думаю, я наконец-то получил то, что вам нужно.
Что вы можете сделать, это написать действительно простое промежуточное ПО, которое отображает вашу схему 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
Обратите внимание, что это решение может быть подвержено гонкам. Здесь мы модифицируем документы глобально, поэтому, если один запрос был запущен, а затем в середине его выполнения второй запрос обрабатывается тем же интерпретатором Python, он будет перезаписан document.cls._meta['db_alias']
Установка и первый запрос начнут запись в ту же базу данных, что ужасно сломает вашу базу данных.
Один и тот же интерпретатор python используется двумя обработчиками запросов, если вы используете многопоточность. Таким образом, с этим решением вы не можете запустить свой сервер с несколькими потоками, только с несколькими процессами.
Чтобы решить проблемы с потоками, вы можете использовать threading.local (). Если вы предпочитаете подход контекстного менеджера, есть также модуль contextvars.
Во время бега connect()
просто назначьте псевдоним для каждой из ваших баз данных, а затем для каждого документа укажите параметр 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'}