0

I'm trying to setup two databases for my django app. The first is used for users and the second for any type of user content. The app is dockerized via docker compose.

Here's the docker-compose.yaml file

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

Below are the db settings of django's 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,
        },

    }
}

Here's the custom router I wrote

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

and finally this is the model I want to get migrated to the mongo db

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

When I try to insert post into the db I get the following error rendered in the browser

MigrationError at /
Table content_manager_post does not exist in database

and the following error in the terminal running the containers with the dbs and the django app.

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

Can I get some help to properly configure mongo and postgres in order to use them. Initially I tried to run the app without default db and custom routers for each of the models I have, but then reverted to this state in order to properly configure one non default db. I also tried wiping out the whole docker volumes and migrations and run it from scratch in order to apply migrations, but I still didn't manage to get it work.

Zarrie
  • 325
  • 2
  • 16

1 Answers1

-2

Hello to use two Database u need this. for more information about multiple databases in Django Read Documents. https://docs.djangoproject.com/en/3.0/topics/db/multi-db/ if my answer was good and helpful select as answered

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'
}
}

Synchronizing your databases¶ The migrate management command operates on one database at a time. By default, it operates on the default database, but by providing the --database option, you can tell it to synchronize a different database. So, to synchronize all models onto all databases in the first example above, you would need to call:

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

If you don’t want every application to be synchronized onto a particular database, you can define a database router that implements a policy constraining the availability of particular models.

If, as in the second example above, you’ve left the default database empty, you must provide a database name each time you run migrate. Omitting the database name would raise an error. For the second example:

$ ./manage.py migrate --database=users
$ ./manage.py migrate --database=customers
DevGUL
  • 19
  • 6
  • for more information about multiple databases read this. https://docs.djangoproject.com/en/3.0/topics/db/multi-db/ – DevGUL Mar 23 '20 at 20:06
  • Hi DevGUL, I did not understand when I migrate one database at a time how do I specify which models go to which database? – Zarrie Mar 23 '20 at 20:24
  • i should specify database like manage.py migrate yourapp --databasename-databaseususer – DevGUL Mar 23 '20 at 20:47
  • you can't specify models you must specify app. because it will be a structure mistake and you need to import and re-import a lot of things so it's will be very ugly. and you will misunderstand your code. just write python3 makemigrations your app and then python3 migrate your app --yourDB=DBuser – DevGUL Mar 23 '20 at 20:49
  • plus don't forget you must connect to Database via setting.py – DevGUL Mar 23 '20 at 20:50