Python
Django

[Django] プロジェクト構成のベストプラクティスを探る - 5.ユーザーモデルに最小限のカスタマイズを入れる

この記事について

Djangoで本番運用やチーム開発を行うに当たって、プロジェクトの初期構成にどのように手を入れたらよいかを、The Twelve Factorsなどを参考にまとめたメモです。

参考

既存のユーザーモデルに手を入れる意味

Djangoのプロジェクトにはユーザーモデルが最初から定義されていますが、このユーザーモデルをそのまま使ってしまうと、データベース定義の関係で後からユーザー定義を拡張しづらくなるので、とりあえず最初にカスタマイズクラスを作ってしまうのがセオリーとされています。

参考:Djangoでは常にカスタムUserを使用すべき

また、デフォルトのユーザーモデルにいくつか問題があるので、合わせて最初から修正しておきましょう。

デフォルトのユーザーモデルの修正点

full_name を追加

英語圏以外の人にとってfirst_nameとlast_nameの方式は扱いに困ります。新たにfull_name(名前)という項目を作り、ユーザー登録画面ではfirst_name、last_nameを非表示にしてしまいましょう。これは「Two Scoop Of Django」で推奨しています。

[任意] アクセス権限項目を非表示にする

「管理者権限(スーパーユーザー権限)」を使えば管理画面上で以下のアクセス制御が可能です。

  • 管理者
    • ユーザー情報の編集を含む全機能が使える
  • 一般スタッフ
    • アプリの利用と管理画面から自分のパスワード変更ができる

段階的な権限設定が必要ないなら「グループ」「ユーザー別パーミッション」の項目は無くてもいいので、ユーザー登録画面で非表示にしましょう。

[任意] 「一般スタッフ権限」のデフォルトをTrueにする

こちらの記事で紹介したような利用者全員にスタッフ権限が必要なアプリでは、スタッフ権限のデフォルトをTrueにしてユーザー登録画面で非表示にしておく方が親切です。

上記の設定を反映させたのが以下のサンプルコードです。

サンプルコード

★ 最初に「users」という名前のアプリケーションを新規追加する。

config/settings.py
INSTALLED_APPS = [
    ...
    'users.apps.UsersConfig',
]

AUTH_USER_MODEL = 'users.User'
users/models.py
from django.db import models
from django.contrib.auth.models import AbstractUser
from django.utils.translation import gettext_lazy as _

class User(AbstractUser):

    # 名前の追加
    full_name = models.CharField(
        verbose_name='名前',
        max_length=100,
        blank=True
    )

    # 既存メソッドの変更
    def get_full_name(self):
        return self.full_name

    # スタッフ権限のデフォルトをTrueに変更
    is_staff = models.BooleanField(
        _('staff status'),
        default=True,
        help_text=_('Designates whether the user can log into this admin site.'),
    )
users/admin.py
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from django.utils.translation import gettext_lazy as _
from .models import User

@admin.register(User)
class AdminUserAdmin(UserAdmin):

    # 変更前コードは django.contrib.auth.admin.py 参照

    fieldsets = (
        (None, {'fields': ('username', 'password')}),
        (_('Personal info'), {'fields': ('full_name', 'email')}),
        (_('Permissions'), {'fields': ('is_active', 'is_superuser')}),
        (_('Important dates'), {'fields': ('last_login', 'date_joined')}),
    )
    list_display = ('username', 'email', 'full_name')
    search_fields = ('username', 'full_name', 'email')

users.apps.py
from django.apps import AppConfig


class UsersConfig(AppConfig):
    name = 'users'
    verbose_name = "ユーザー管理"