使用環境
Windows11
python3.11
Django4.2
プロジェクトとアプリを作成します。
> mkdir /path/to/kobushi
> django-admin startproject kobushi .
> mkdir user/accounts
> python .\manage.py startapp accounts kobushi/user/accounts
accountsアプリをkobushiプロジェクトの中に生成します。
サブディレクトリ以降にアプリを作成する際は、そこまでのディレクトリが存在している必要があります。
そのため、事前にディレクトリを作成してからアプリを作成します。
次にsettings.pyにて設定を追加します。
# kobushi/settings.py
INSTALLED_APPS = [
...
'kobushi.user.accounts', # add
...
]
AUTH_USER_MODEL = "accounts.User"
ここで、AUTH_USER_MODELの定義について、
[app_label].[ModelName]
として決まっています。そのため、
AUTH_USER_MODEL = "kobushi.user.accounts.User"
という定義方法はできません。この設定を行うと、createsuperuser等のコマンド実行時に次のエラーが表示されます。
ValueError: Invalid model reference 'kobushi.user.accounts.User'. String model references must be of the form 'app_label.ModelName'.
Djangoの定義によると、AppConfigの定義によって設定する値が決まるようです。
参考:https://docs.djangoproject.com/ja/5.1/ref/applications/
ーー
設定可能な属性
AppConfig.name
アプリケーションへの Python フルパス、たとえば 'django.contrib.admin' 。
この属性は設定がどのアプリケーションに適用されるかを定義します。
全ての AppConfig サブクラスで設定する必要があります。
Djangoプロジェクト全体の中で固有である必要があります。
AppConfig.label
アプリケーション用のショートネーム 例 'admin'
この属性により、2つのアプリケーションのラベルが競合している場合に、
アプリケーションのラベルを変更できます。デフォルトは name の最後のコンポーネントです。
これは有効な Python 識別子でなければなりません。
Djangoプロジェクト全体の中で固有である必要があります。
ーー
# kobushi/user/accounts/apps.py
class AccountsConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'kobushi.user.accounts'
INSTALLED_APPSの定義では'kobushi.user.accounts'を追加しているため、
apps.pyのnameと一致する必要があります。そして、この場合のlabelは'accounts'になります。
※上記の公式サイトにて"デフォルトは name の最後のコンポーネントです。"と記載されているので、
ドットで区切った最後の文字列が該当します。
ちなみに、name = 'accounts' としてしまうと、createsuperuser等のコマンド実行時に次のエラーが表示されます。
django.core.exceptions.ImproperlyConfigured: Cannot import 'accounts'. Check that 'kobushi.user.accounts.apps.AccountsConfig.name' is correct.
次にカスタムユーザモデルを定義します。
# kobushi/user/accounts/models.py
from django.db import models
from django.contrib.auth.models import (BaseUserManager, AbstractBaseUser, PermissionsMixin)
from django.utils.translation import gettext_lazy as _
class UserManager(BaseUserManager):
def _create_user(self, email, username, password, **extra_fields):
email = self.normalize_email(email)
user = self.model(email=email, username=username, **extra_fields)
user.set_password(password)
user.save(using=self._db)
return user
def create_user(self, email, username, password=None, **extra_fields):
extra_fields.setdefault('is_active', True)
extra_fields.setdefault('is_staff', False)
extra_fields.setdefault('is_superuser', False)
return self._create_user(email=email, username=username, password=password, **extra_fields)
def create_superuser(self, email, username, password, **extra_fields):
extra_fields['is_active'] = True
extra_fields['is_staff'] = True
extra_fields['is_superuser'] = True
return self._create_user(email=email, username=username, password=password, **extra_fields)
class User(AbstractBaseUser, PermissionsMixin):
username = models.CharField(
verbose_name=_("username"), unique=True, max_length=150
)
email = models.EmailField(
verbose_name=_("email"), unique=True
)
nick_name = models.CharField(
verbose_name=_("nick_name"), max_length=150, null=True, blank=False
)
first_name = models.CharField(
verbose_name=_("first_name"), max_length=150, null=True, blank=False
)
last_name = models.CharField(
verbose_name=_("last_name"), max_length=150, null=True, blank=False
)
avator = models.ImageField(
verbose_name=_("avators"), upload_to='avators', null=True, blank=True
)
profile = models.CharField(
verbose_name=_("profile"), max_length=1000, null=True, blank=True
)
is_superuser = models.BooleanField(
verbose_name=_("is_superuer"), default=False
)
is_staff = models.BooleanField(
verbose_name=_('staff status'), default=False,
)
is_active = models.BooleanField(
verbose_name=_('active'), default=True,
)
regtm = models.DateTimeField(
verbose_name=_("regtm"), auto_now_add=True
)
modtm = models.DateTimeField(
verbose_name=_("modtm"), auto_now=True
)
objects = UserManager()
USERNAME_FIELD = 'username'
REQUIRED_FIELDS = ['email']
あとは、
> python manage.py makemigrations
> python mange.py migrate
にて、カスタムモデルユーザのデータベーステーブルが作成されます。
どうも、AbstractBaseUserを継承してカスタムユーザモデルの定義を行うにあたり、
usernameの定義が必要になっているようです。
参考にしたサイトだと、username定義せず、
代わりにaccount_idをUSERNAME_FIELDに設定しているので、
通るはずなんですけどね...
参考にしたサイトの定義で進めると、createsuperuser等のコマンド実行時に次のエラーが表示されました。
理由は・・・謎です。
SystemCheckError: System check identified some issues:
ERRORS:
: (admin.E033) The value of 'ordering[0]' refers to 'username', which is not a field of 'accounts.User'.
: (admin.E108) The value of 'list_display[0]' refers to 'username', which is not a callable, an attribute of 'UserAdmin', or an attribute or method on 'accounts.User'.
参考サイト:
https://qiita.com/ryo-keima/items/e6ce42bb4c11432ea829
Comment
現在、コメントはありません。