Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Running makemigrations when using multiple databases

Tags:

django

I've set up my Django project to use two databases. One is read-only and other is the "default" django database for the rest of the project.

Here are the settings:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': 'sipf',
        'USER': 'myusername',
        'PASSWORD': 'secret',
        'HOST': '127.0.0.1',
        'PORT': '5432',
    }
    ,
    'my_read_only_db': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'my_read_only_db',
        'USER': 'myusername',
        'PASSWORD': 'mypassword',
        'HOST': 'remote.host.edu',
    }
}

Here is router.py for the read-only DB:

class MyReadOnlyDBRouter(object):

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

and for the default DB:

class PrimaryRouter(object):
    def db_for_read(self, model, **hints):
        return 'default'

    def db_for_write(self, model, **hints):
        return 'default'

    def allow_relation(self, obj1, obj2, **hints):
        db_list = 'default'
        if obj1._state.db in db_list and obj2._state.db in db_list:
            return True
        return None

    def allow_migrate(self, db, app_label, model_name=None, **hints):
        return True

And finally the routing in settings:

DATABASE_ROUTERS = ['my_read_only_db.router.MyReadOnlyDBRouter', 'common.router.PrimaryRouter']

I understand that when running migrate one needs to specify which database to run against like so:

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

However, before even getting that far one needs to run makemigrations. Here, it is clearly attempting to create tables in the read-only database and I'm getting:

django.db.migrations.exceptions.MigrationSchemaMissing: Unable to create the django_migrations table ((1142, "CREATE command denied to user 'user'@'example.com' for table 'django_migrations'"))

Whereas it should not even be attempting to do this as the django_migrations table should be in the default database which does have write abilities.

like image 728
Tomislav Urban Avatar asked Oct 30 '22 02:10

Tomislav Urban


1 Answers

From the django source code, django/core/management/commands/makemigrations.py:

# Non-default databases are only checked if database routers used.
aliases_to_check = connections if settings.DATABASE_ROUTERS else [DEFAULT_DB_ALIAS]
for alias in sorted(aliases_to_check):
    connection = connections[alias]
    if (connection.settings_dict['ENGINE'] != 'django.db.backends.dummy' and any(
            # At least one model must be migrated to the database.
            router.allow_migrate(connection.alias, app_label, model_name=model._meta.object_name)
            for app_label in consistency_check_labels
            for model in apps.get_app_config(app_label).get_models()
    )):
        loader.check_consistent_history(connection)

If you're using database routers, it will attempt to check for a consistent history on every database connection. If you temporarily disable your database router or readonly database by commenting out the config, you can run makemigrations without it making a database connection, then you can add them back.

like image 141
Razzi Abuissa Avatar answered Nov 18 '22 08:11

Razzi Abuissa