Используйте mongodb в качестве второй базы данных для приложения django - PullRequest
0 голосов
/ 23 марта 2020

Я пытаюсь настроить две базы данных для моего приложения django. Первый используется для пользователей, а второй - для любого типа пользовательского контента. Приложение докеризируется с помощью docker compose.

Вот файл docker -compose.yaml

version: '3'

services:
  postgres:
    image: postgres:latest
    environment:
      - POSTGRES_PASSWORD=test
    ports:
      - "5432:5432"
    restart: always
  mongodb:
    image: mongo:latest
    command: ["--bind_ip_all"]
    ports:
      - "27017:27017"
    restart: always
  django:
    build: .
    command: bash -c "
        python service_platform/manage.py makemigrations &&
        python service_platform/manage.py migrate &&
        python service_platform/manage.py runserver 0.0.0.0:8000
      "
    volumes:
      - .:/code
    ports:
      - "8000:8000"
    depends_on:
      - postgres
      - mongodb
    links:
      - postgres
      - mongodb

Ниже приведены настройки БД для django settings.py

DATABASE_ROUTERS = [
    'content_manager.content_db_router.ContentDBRouter',
]

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': 'postgres',
        'USER': 'postgres',
        'HOST': 'postgres',
        'PASSWORD': 'test',
        'PORT': 5432,
    },
    'content': {
        'ENGINE': 'djongo',
        'NAME': 'mongodb',
        'CLIENT': {
            'host': 'mongodb',
            'port': 27017,
        },

    }
}

Вот пользовательский роутер, который я написал

class ContentDBRouter(object):

    content_db = 'content'
    default_db = 'default'

    def db_for_read(self, model, **hints):
        if model._meta.app_label == 'content_manager':
            return self.content_db
        return None

    def db_for_write(self, model, **hints):
        if model._meta.app_label == 'content_manager':
            return self.content_db
        return None

    def allow_migrate(self, db, app_label, model_name=None, **hints):
        if db == self.content_db:
            return True
        elif db == self.default_db:
            return True
        else:
            raise Exception(f'DB with id {db} not found!')

и, наконец, это модель, которую я хочу перенести на mon go db

class Post(models.Model):
    id = models.AutoField(primary_key=True)
    title = models.TextField(default='default title')

Когда я пытаюсь вставить сообщение в базу данных, я получаю следующую ошибку в браузере

MigrationError at /
Table content_manager_post does not exist in database

и следующую ошибку в терминале, выполняющем контейнеры с базой данных и приложением django.

raise MigrationError(f'Table {collection} does not exist in database')

Могу ли я получить некоторую помощь для правильной настройки mon go и postgres для их использования. Сначала я пытался запустить приложение без базы данных по умолчанию и пользовательских маршрутизаторов для каждой из имеющихся у меня моделей, но затем вернулся в это состояние, чтобы правильно настроить одну базу данных не по умолчанию. Я также попытался стереть целые docker томов и миграций и запустить его с нуля, чтобы применить миграцию, но мне так и не удалось заставить его работать.

1 Ответ

0 голосов
/ 23 марта 2020

Здравствуйте, чтобы использовать две базы данных вам нужно это. для получения дополнительной информации о нескольких базах данных в Django Read Documents. https://docs.djangoproject.com/en/3.0/topics/db/multi-db/ если мой ответ был хорошим и полезным, выберите в качестве ответа

DATABASES = {
'default': {},
'users': {
    'NAME': 'user_data',
    'ENGINE': 'django.db.backends.mysql',
    'USER': 'mysql_user',
    'PASSWORD': 'superS3cret'
},
'customers': {
    'NAME': 'customer_data',
    'ENGINE': 'django.db.backends.mysql',
    'USER': 'mysql_cust',
    'PASSWORD': 'veryPriv@ate'
}
}

Синхронизация баз данных¶ Команда управления переносом работает одновременно с одной базой данных. По умолчанию он работает с базой данных по умолчанию, но, предоставив опцию --database, вы можете настроить синхронизацию другой базы данных. Таким образом, чтобы синхронизировать все модели со всеми базами данных в первом примере выше, вам нужно вызвать:

$ ./manage.py migrate
$ ./manage.py migrate --database=users

Если вы не хотите, чтобы каждое приложение было синхронизировано с конкретной базой данных, вы можете определить Маршрутизатор базы данных, который реализует политику, ограничивающую доступность определенных моделей.

Если, как и во втором примере выше, вы оставили базу данных по умолчанию пустой, вы должны указывать имя базы данных при каждом запуске миграции. Если имя базы данных пропущено, возникнет ошибка. Для второго примера:

$ ./manage.py migrate --database=users
$ ./manage.py migrate --database=customers
...