Django fails to create superuser in other db than 'default'

Question:

Is it a bug or am I wrong ?
I am at the step to create a superuser, but django want a table in wrong db despite my router seems to work :

settings.py

DATABASES = {
      'intern_db': {
        'ENGINE': 'mysql.connector.django',
        'NAME': 'django_cartons',
            'USER': 'root',
            'PASSWORD' : '',
      },
    'default': {
        'ENGINE': 'mysql.connector.django',
        'NAME': 'cartons',
            'USER': 'root',
            'PASSWORD' : '',
    }
}

DATABASE_ROUTERS = ['web.routers.AuthRouter']

routers.py

class AuthRouter(object):
      """
      A router to control all database operations on models in the
      auth application.
      """
      def db_for_read(self, model, **hints):
            """
            Attempts to read auth models go to auth.
            """
            print("READ ",model._meta.app_label)
            if model._meta.app_label in ['auth', 'contenttypes', 'admin', 'sessions']:
               print(True)
               return 'intern_db'
            return None

      def db_for_write(self, model, **hints):
            """
            Attempts to write auth models go to auth.
            """
            print("WRITE ",model._meta.app_label)
            if model._meta.app_label in ['auth', 'contenttypes', 'admin', 'sessions']:
               print(True)
               return 'intern_db'
            return None

      def allow_relation(self, obj1, obj2, **hints):
            """
            Allow relations if a model in the auth app is involved.
            """
            print("REL ", obj1._meta.app_label, ' ', obj2._meta.app_label)
            if obj1._meta.app_label in ['auth', 'contenttypes', 'admin', 'sessions'] or 
               obj2._meta.app_label in ['auth', 'contenttypes', 'admin', 'sessions']:
               return True
            return None

      def allow_migrate(self, db, model):
            """
            Make sure the auth app only appears in the 'auth'
            database.
            """
            if db == 'intern_db':
               return (model._meta.app_label in ['auth', 'contenttypes', 'admin', 'sessions'])
            elif model._meta.app_label in ['auth', 'contenttypes', 'admin', 'sessions']:
               return False
            return None

command :

$> ./manage.py createsuperuser
READ  auth
True
READ  auth
True
Username (leave blank to use 'leo'): admin
Traceback (most recent call last):
  File "/usr/lib/python3.4/site-packages/mysql/connector/django/base.py", line 115, in _execute_wrapper
    return method(query, args)
  File "/usr/lib/python3.4/site-packages/mysql/connector/cursor.py", line 507, in execute
    self._handle_result(self._connection.cmd_query(stmt))
  File "/usr/lib/python3.4/site-packages/mysql/connector/connection.py", line 722, in cmd_query
    result = self._handle_result(self._send_cmd(ServerCmd.QUERY, query))
  File "/usr/lib/python3.4/site-packages/mysql/connector/connection.py", line 640, in _handle_result
    raise errors.get_exception(packet)
mysql.connector.errors.ProgrammingError: 1146 (42S02): Table 'cartons.auth_user' doesn't exist

As you can see, it looks for ‘cartons.auth_user’ that doesn’t exist (it should be ‘django_cartons’ aliased by ‘intern_db’ instead)
However, my router is called and return the right result as we see “READ auth” and “TRUE” in the command output…

Any Idea ?

Asked By: hl037_

||

Answers:

The thing is the system is somewhat broken : it respects the config for some task but not for others (the 2 first “TRUE” in the output) but it doesn’t for other and use default.

This is perhaps intended even if weird (actually nothing forbid to have several admin db, and that permits not have automatic dark choices).

Actually to create the SU in another db, and for any usage of these command, you must pass the database where you want to create it explicitly :

./manage.py createsuperuser --database=intern_db

NOTE : the db name is the alias in the config.

Answered By: hl037_

You need to make migrations to your database before creating a superuser. To make migrations

user@root:~$python manage.py migrate

This will create the auth_user table in your database.

Answered By: mudit

If you come here and use a PostgreSQL database, then you might need to configure schema with the search_path option.

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': os.environ['DB_NAME'],
        'USER': os.environ['USERNAME'],
        'PASSWORD': os.environ['PASSWORD'],
        'HOST': os.environ['HOSTNAME'],
        'PORT': os.environ['PORT'],
        'OPTIONS': {
            'options': '-c search_path=public'
        }
    },
    'auth_db': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': os.environ['AUTH_DB_NAME'],
        'USER': os.environ['AUTH_USERNAME'],
        'PASSWORD': os.environ['AUTH_PASSWORD'],
        'HOST': os.environ['AUTH_HOSTNAME'],
        'PORT': os.environ['AUTH_PORT'],
        'OPTIONS': {
            'options': '-c search_path=public'
        }
    },
}

Then write migrations and create superuser:

python manage.py migrate --database=auth_db
python manage.py createsuperuser --database=auth_db
Answered By: Florent
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.