2

Environment: Django 2, Python 3.6, PostgreSQL (optional)

I am writing an application with multiple models, some of them might be stored in different databases.

Example:

models.py (might be in different apps)

# this used to allow field 'database' to be processed in 'Meta'
models.options.DEFAULT_NAMES = models.options.DEFAULT_NAMES + ('database', )

class MyModel01(models.Model):
    ...
    # this goes to default database


class MyModel02(models.Model):
    ...

    class Meta:
        database = 'mydb02'


class MyModel03(models.Model):
    ...

    class Meta:
        database = 'mydb03'

routers.py:

class MyRouter(object):
    def db_for_read(self, model, **hints):
        return getattr(model._meta, 'database', None)

    def db_for_write(self, model, **hints):
        return getattr(model._meta, 'database', None)

    def allow_migrate(self, db, app_label, model_name=None, **hints):
        model = hints.get('model')
        if not model:
            return None
        if db != 'default':
            modelname = model_name or model._meta.model_name
            usedb = getattr(model._meta, 'database', None)
            if not usedb:
                return False

            if modelname and usedb:
                return usedb == db
            return False
        else:
            usedb = getattr(model._meta, 'database', 'default')
            return usedb == db
        return None

settings:

DATABASES: {
    'default': {
        # some db settings
    },
    'mydb02': {
        # db settings
    },
    'mydb03': {
        # the SAME db settings as for mydb02
    }
}

The issue is that in settings there might be the same database set for all database aliases.

When I run migrate the migration get applied to just one of the databases, but not always to required one. For example it gets applied to 'default', but not 'mydb03'.

I suppose the mistake is in my router, but cannot find out correct implementation.

6
  • It seems the issue is hard to track and to fix. I ended up with having different schemas inside one database (postgresql). Commented Apr 16, 2018 at 21:20
  • Do you use any options config? Like this:"'options': -c search_path=schema, public" If yes, try remove the public after comma. Commented Sep 9, 2019 at 20:04
  • Yes, but this does not solve the issue at all. And you might have not only postgres. Commented Sep 11, 2019 at 10:57
  • I have this problem too, with multipls schemas(each schema is a distinct database on django settings), but removing public in options works for me. Commented Sep 11, 2019 at 12:53
  • In my case they were the same databases and schemas on one of environments. And this is exactly the problem - where migrations table is stored. Commented Sep 11, 2019 at 14:50

1 Answer 1

2

You can specify which database to use:

python3 manage.py migrate # default database
python3 manage.py migrate --database mydb02
python3 manage.py migrate --database mydb03

https://docs.djangoproject.com/en/2.0/topics/db/multi-db/#synchronizing-your-databases

Sign up to request clarification or add additional context in comments.

2 Comments

Yes, of course, and this is the only way to run migration for other db aliases. But if 'default' goes first - it might receive the migration, not intended for it. That's the issue.
You can config a routerdb to ignore some models in public. It's work for me.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.