使用mongodb作为Django应用程序的第二个数据库

时间:2020-03-23 19:57:57

标签: django mongodb djongo

我正在尝试为我的Django应用程序设置两个数据库。第一个用于用户,第二个用于任何类型的用户内容。该应用通过docker compose进行了Docker化。

这是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!')

最后这是我想要迁移到mongo db的模型

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

当我尝试在数据库中插入post时,在浏览器中出现以下错误

MigrationError at /
Table content_manager_post does not exist in database

以及运行带有dbs和django应用程序的容器的终端中的以下错误。

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

我可以得到一些帮助来正确配置mongo和postgres以便使用它们吗? 最初,我尝试在没有默认数据库和自定义路由器的情况下针对我拥有的每个模型运行该应用程序,但随后恢复到此状态以正确配置一个非默认数据库。 我还尝试清除了整个docker卷和迁移,并从头开始运行它以应用迁移,但是我仍然没有设法使其正常工作。

1 个答案:

答案 0 :(得分:0)

您好要使用两个数据库,您需要此。有关Django阅读文档中的多个数据库的更多信息。 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'
}
}

同步数据库¶ migration management命令一次在一个数据库上运行。默认情况下,它在默认数据库上运行,但是通过提供--database选项,您可以告诉它同步另一个数据库。因此,要在上述第一个示例中将所有模型同步到所有数据库上,您需要调用:

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

如果您不希望每个应用程序都同步到一个特定的数据库中,则可以定义一个数据库路由器,以实施限制特定模型可用性的策略。

如果像上面的第二个示例一样,将默认数据库留空,则每次运行迁移时必须提供一个数据库名称。省略数据库名称将引发错误。对于第二个示例:

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