# Django Model custom User creates auth\_user table in my app database when using multiple databases

**URL:** <https://forum.djangoproject.com/t/django-model-custom-user-creates-auth-user-table-in-my-app-database-when-using-multiple-databases/15365>\
**Category:** Using the ORM\
**Created:** [August 11, 2022, 3:29pm UTC](https://forum.djangoproject.com/t/django-model-custom-user-creates-auth-user-table-in-my-app-database-when-using-multiple-databases/15365 "2022-08-11T15:29:53Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![andez2000](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/andez2000/32/9651_2.png) [@andez2000](https://forum.djangoproject.com/u/andez2000)\
**Post date:** [August 11, 2022, 3:29pm UTC](https://forum.djangoproject.com/t/django-model-custom-user-creates-auth-user-table-in-my-app-database-when-using-multiple-databases/15365/1 "2022-08-11T15:29:53Z")

</div>

This is fresh from my stack overflow post… Really could do with some help here…

I’ve created a new project from scratch. By default it uses the `auth` package for user and permission management.

Given the following from official Django Docs

> Using a custom user model when starting a project¶  
> If you’re starting a new project, it’s highly recommended to set up a custom user model, even if the default User model is sufficient for you. This model behaves identically to the default user model, but you’ll be able to customize it in the future if the need arises:

I am wanting to override the default User - using [AbstractBaseUser](https://docs.djangoproject.com/en/4.1/topics/auth/customizing/#django.contrib.auth.models.AbstractBaseUser).

I am trying to setup this in a multi-database environment. One database for the auth, ‘contenttypes’, ‘sessions’, and ‘admin’. And the other for my application related stuff.

Having created migrations and executed them on my databases, the `auth_user` table resides in my application database - not the `auth` database.

Is this expected behaviour? I was expecting - and I want the `auth_user` table to reside in the `auth` database.

Is there a way to make the auth\_user reside in the `auth` database?

## Create Project

```console
py -m venv venv
venv\scripts\activate
pip install django

django-admin startproject core .
py manage.py startapp acmeapp

```

**acmeapp/models.py**

```python
from django.db import models
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager

class Foo(models.Model):
    foo_id = models.BigAutoField(primary_key=True)
    name = models.TextField()

    class Meta:
        db_table = 'foos'

class AccountManager(BaseUserManager):
    """
    The management class to handle user creation.
    """

    def create_user(self, username, password=None):
        if not username:
            raise ValueError(_('The Username must be set'))

        user = self.model(username=username)
        user.set_password(password)
        user.save()
        return user

    def create_superuser(self, username, password=None):
        return self.create_user(username, password)

class Account(AbstractBaseUser):

    """
    The custom user model.
    """
    username = models.CharField(max_length=40, unique=True)
    email = None
    USERNAME_FIELD = 'username'
    REQUIRED_FIELDS = ['access_platforms', 'access_missions', 'access_rule_sets', 'access_mdsr']

    objects = AccountManager()

    def __str__ (self):
        return ''.join(c for c in self.username if c.isupper())

    class Meta:
        db_table = 'auth_user'
                

```

**core/settings.py**

```python
DATABASES = {
    'default': {},
    'auth_db': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': BASE_DIR / 'auth_db.sqlite3',
        "TEST": {
            "NAME": "auth_db",
            'DEPENDENCIES': [],
        },
    },
    'acmeapp_db': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': BASE_DIR / 'acmeapp_db.sqlite3',
        "TEST": {
            "NAME": "acmeapp_db",
            'DEPENDENCIES': [],
        },
    }
}

DATABASE_ROUTERS = [
    'core.db_routers.AuthRouter',
    'core.db_routers.AcmeAppRouter'
]

AUTH_USER_MODEL = 'acmeapp.Account'

```

**core/db\_routers**

```python
from acmeapp.models import Account

class AuthRouter:
    route_app_labels = ['auth', 'contenttypes', 'sessions', 'admin']

    def db_for_read(self, model, **hints):
        if model._meta.app_label in self.route_app_labels:
            return 'auth_db'
        
        if model == Account:
            return 'auth_db'

        return None

    def db_for_write(self, model, **hints):
        if model._meta.app_label in self.route_app_labels:
            return 'auth_db'
        
        if model == Account:
            return 'auth_db'

        return None

    def allow_relation(self, obj1, obj2, **hints):
        if (
                obj1._meta.app_label in self.route_app_labels or
                obj2._meta.app_label in self.route_app_labels
        ):
            return True

        return None

    def allow_migrate(self, db, app_label, model_name=None, **hints):
        if app_label in self.route_app_labels:
            return db == 'auth_db'
        
        return None
    
    
class AcmeAppRouter:
    route_app_labels = ['acmeapp']

    def db_for_read(self, model, **hints):
        if model._meta.app_label in self.route_app_labels:
            return 'acmeapp_db'

        return None

    def db_for_write(self, model, **hints):
        if model._meta.app_label in self.route_app_labels:
            return 'acmeapp_db'

        return None

    def allow_relation(self, obj1, obj2, **hints):
        if (
                obj1._meta.app_label in self.route_app_labels or
                obj2._meta.app_label in self.route_app_labels
        ):
            return True

        return None

    def allow_migrate(self, db, app_label, model_name=None, **hints):
        if app_label in self.route_app_labels:
            return db == 'acmeapp_db'
        return None

```

## Make and Apply Migrations

Once the above code is created, I create migrations and apply them to each database.

```console
py manage.py makemigrations
py manage.py migrate --database=acmeapp_db
py manage.py migrate --database=auth_db

```

**/acmeapp/migrations/0001\_initial.py**

```python
# Generated by Django 4.0.4 on 2022-08-11 07:50

from django.db import migrations, models

class Migration(migrations.Migration):

    initial = True

    dependencies = [
    ]

    operations = [
        migrations.CreateModel(
            name='Account',
            fields=[
                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                ('password', models.CharField(max_length=128, verbose_name='password')),
                ('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last login')),
                ('username', models.CharField(max_length=40, unique=True)),
            ],
            options={
                'db_table': 'auth_user',
            },
        ),
        migrations.CreateModel(
            name='Foo',
            fields=[
                ('mission_id', models.BigAutoField(primary_key=True, serialize=False)),
                ('name', models.TextField()),
                ('retired', models.BooleanField(default=False)),
            ],
            options={
                'db_table': 'foos',
            },
        ),
    ]

```

Which has the two models including Account.

As a result the two databases are created and have tables as follows:

**acmeapp\_db.sqlite**

auth\_user  
django\_migrations  
foos  
sqlite\_sequence

**auth\_db.sqlite**

auth\_group  
auth\_group\_permissions  
auth\_permission  
django\_admin\_log  
django\_content\_type  
django\_migrations  
django\_session  
sqlite\_sequence

## Research

I have not found an answer to the problem. Every blog post on setting this up never covers the what happens in this scenario.

I havent found an answer in any Django documentation either.

Curiously, [https://code.djangoproject.com/wiki/MultipleDatabaseSupport](https://code.djangoproject.com/wiki/MultipleDatabaseSupport)

> Different models/applications living on different databases, for example a ‘blog’ application on db1 and a forum application on db2. This should include the ability to assign a different database to an existing application without modifying it, e.g. telling Django where to keep the django.contrib.auth.User table.

---

<div class="post-metadata">

**Author:** ![KenWhitesell](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/kenwhitesell/32/280_2.png) [@KenWhitesell](https://forum.djangoproject.com/u/KenWhitesell)\
**Post date:** [August 11, 2022, 4:05pm UTC](https://forum.djangoproject.com/t/django-model-custom-user-creates-auth-user-table-in-my-app-database-when-using-multiple-databases/15365/2 "2022-08-11T16:05:00Z")

</div>

Reread the section about Routers in the multiple databases docs.

Returning None from a router test method does not mean “do not do this”, it means “this router doesn’t care”.

---

<div class="post-metadata">

**Author:** ![andez2000](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/andez2000/32/9651_2.png) [@andez2000](https://forum.djangoproject.com/u/andez2000)\
**Post date:** [August 12, 2022, 8:13am UTC](https://forum.djangoproject.com/t/django-model-custom-user-creates-auth-user-table-in-my-app-database-when-using-multiple-databases/15365/3 "2022-08-12T08:13:41Z")

</div>

Thanks for the response Ken.

Yep - I understood it meant the router didn’t care. However, I’ve gone back through and debugged the router logic when applying migrations. I _think_ it was out somewhat.

**AuthRouter**

```python
def allow_migrate(self, db, app_label, model_name=None, **hints):
        
        if app_label in self.route_app_labels or model_name == 'account':
            return db == 'auth_db'
        
        
        return None

```

**AcmeAppRouter**

```python
def allow_migrate(self, db, app_label, model_name=None, **hints):
        
        if app_label in self.route_app_labels and model_name != 'account':
            return db == 'acmeapp_db'
        

        return None

```

Which gives the error when migrating the auth\_db with:

```auto
sqlite3.OperationalError: table "auth_user" already exists

```

Which makes sense as the migrations applied would have created that table in the auth package - assuming it would be in `auth.0001_initial`.

Do we have any user customisation guidance at this point. I’ve tried looking back here - [Customizing authentication in Django | Django documentation | Django (djangoproject.com)](https://docs.djangoproject.com/en/4.0/topics/auth/customizing/#using-a-custom-user-model-when-starting-a-project).

Although there was never a hint around adding Meta to the user class to specify the table which we have done here:

```python
class Meta:
        db_table = 'auth_user'

```

Changing the table name to something else `super_duper_auth_user` fixes the issue. Additionally the `auth_user` table **is not created**.

I am assuming this was the other issue at play here - although I am slightly confused given sqlite3.OperationalError: table “auth\_user” already exists - but where did it disappear to when I changed that Meta db\_table.

I hope the changes look ok to you here.

Thanks

Paul

---

<div class="post-metadata">

**Author:** ![KenWhitesell](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/kenwhitesell/32/280_2.png) [@KenWhitesell](https://forum.djangoproject.com/u/KenWhitesell)\
**Post date:** [August 12, 2022, 12:04pm UTC](https://forum.djangoproject.com/t/django-model-custom-user-creates-auth-user-table-in-my-app-database-when-using-multiple-databases/15365/4 "2022-08-12T12:04:29Z")

</div>

Side note: Personally, I would find it confusing to have two separate routers - especially if your tables should only belong in one database.

We use a slightly different technique. We create a dict mapping the app to a database, and so our various methods do things like:  
`return target_db[app_label]` or `return target_db.get(app_label, 'default')` depending on the system.  
(target\_db might end up looking something like this:  
`target_db = {'app1': 'db1', 'app2': 'db1', 'app3': 'db2', ...}`)

This allows us to keep all the logic in a single router - we find it easier that way.

---

<div class="post-metadata">

**Author:** ![andez2000](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/andez2000/32/9651_2.png) [@andez2000](https://forum.djangoproject.com/u/andez2000)\
**Post date:** [August 13, 2022, 4:55pm UTC](https://forum.djangoproject.com/t/django-model-custom-user-creates-auth-user-table-in-my-app-database-when-using-multiple-databases/15365/5 "2022-08-13T16:55:19Z")

</div>

OK thanks… We are just getting our feet wet with Django so to speak… Any advice is welcomed. I don’t think we are anticipating connecting any further databases up so will look at merging.
