Django Model custom User создает таблицу auth_user в базе данных моего приложения при использовании нескольких баз данных
Я создал новый проект с нуля. По умолчанию он использует пакет auth
для управления пользователями и разрешениями.
Я хочу переопределить пользователя по умолчанию - используя AbstractBaseUser.
Создав миграции и выполнив их на моих базах данных, таблица auth_user
находится в моей базе данных приложения - не в базе данных auth
.
Является ли это ожидаемым поведением? Я ожидал - и хочу, чтобы таблица auth_user
находилась в базе данных auth
.
Создать проект
py -m venv venv
venv\scripts\activate
pip install django
django-admin startproject core .
py manage.py startapp acmeapp
acmeapp/models.py
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
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
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
Создание и применение миграций
После создания вышеуказанного кода, я создаю миграции и применяю их к каждой базе данных.
py manage.py makemigrations
py manage.py migrate --database=acmeapp_db
py manage.py migrate --database=auth_db
/acmeapp/migrations/0001_initial.py
# 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',
},
),
]
У которой есть две модели, включая Account.
В результате две базы данных созданы и имеют таблицы следующего вида:
acmeapp_db.sqlite
auth_db.sqlite