Django

Djangoで開発・データベース/Custom User Model作成とログイン画面実装

Djangoカスタムユーザーを作成する

Djangoには、デフォルトのUserとカスタムユーザーモデルがあり、公式サイトではカスタムユーザーを作成することを強く推奨されています。なら、カスタムユーザーだけでいんじゃない???

まぁ、そんなことは置いといて‥

注意しないといけないことは、最初に実行するmanage.py migrateをする前にしければならないことです。公式サイトにもあとでやるには大変だからねーと書いています。

django.contrib.auth.base_user.AbstractBaseUser
django.contrib.auth.models.AbstractUser

どちらかを継承してカスタムユーザを作るのですが、難しいらしいですが「AbstractBaseUser」を継承して作っていきます。

カスタムユーザー用のaccountsのアプリを作成する

作成の仕方は、こちらの記事「Djangoではカスタムユーザを作るべきらしい」を参考に作成しました。

テーブル作成までは、リンク先の記事を参照して作ってみてください

from django.contrib.auth.base_user import AbstractBaseUser, BaseUserManager
from django.core.mail import send_mail
from django.db import models
from django.utils import timezone
from django.utils.translation import gettext_lazy as _

from django.contrib.auth.models import PermissionsMixin, UserManager

from django.contrib.auth.validators import UnicodeUsernameValidator


class CustomUser(AbstractBaseUser, PermissionsMixin):
    username_validator = UnicodeUsernameValidator()
    username = models.CharField(
        _('username'),
        max_length=7,
        unique=True,
        help_text=_('社員番号7桁'),
        validators=[username_validator],
        error_messages={
            'unique': _("すでに登録されている社員番号です"),
        },
    )
    first_name = models.CharField(_('姓'), max_length=30, blank=True)
    last_name = models.CharField(_('名'), max_length=150, blank=True)
    email = models.EmailField(_('Eメール'), blank=True)
    is_staff = models.BooleanField(
        _('管理者'),
        default=False,
        help_text=_('管理サイトにログインできるかどうか'),
    )
    is_active = models.BooleanField(
        _('退社済'),
        default=True,
        help_text=_(
            '無効フラグ'
        ),
    )
    date_joined = models.DateTimeField(_('date joined'), default=timezone.now)

    objects = UserManager()

    EMAIL_FIELD = 'email'
    USERNAME_FIELD = 'username'
    REQUIRED_FIELDS = ['email']

    class Meta:
        verbose_name = _('user')
        verbose_name_plural = _('users')
        # abstract = True

    def clean(self):
        super().clean()
        self.email = self.__class__.objects.normalize_email(self.email)

    def get_full_name(self):
        full_name = '%s %s' % (self.first_name, self.last_name)
        return full_name.strip()

    def get_short_name(self):
        return self.first_name

    def email_user(self, subject, message, from_email=None, **kwargs):
        """Send an email to this user."""
        send_mail(subject, message, from_email, [self.email], **kwargs)

Django AbstractBaseUserのでデータベースが作成され管理画面をみてみる

ここからは、管理画面に表示するための設定をします。

先ほど作ったaccountsのadminに追記します。

from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from .models import CustomUser


admin.site.register(CustomUser, UserAdmin)

見事管理画面が開くことができたと思います。

CTRL + C で一度サーバーを停止します。

ユーザーマスタに入社日と退社日を追加してもう一度マイグレーションしようと思います。

models.pyに2行追加します

    nyusha_date = models.DateField(_('入社日'), blank=True)
    taisha_date = models.DateField(_('退社日'), blank=True, null=True,)

追加したものを管理画面で表示されるようにadmin.pyに追記します。

from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from .models import CustomUser

UserAdmin.fieldsets += ('Custom fields set', {'fields': ('nyusha_date', 'taisha_date')}),
admin.site.register(CustomUser, UserAdmin)

大切なのは、+=で自分で追加したフィールドを指定しているところです。こちらで追加したうえで、管理サイトを開いてねってことだと思いますね

もう一度マイグレーションしてサーバーを起動させます。

項目が追加しているので、makemigrationsをしたときに初期値どうしますか?と質問されますので、1を選んでtimezone.nowを指定すれば現在時刻でセットしてくれます。

python manage.py makemigrations
python manage.py migrate  
python manage.py createsuperuser

これで作り直しが完了です。

サーバーを起動して管理画面をみようと思います

python manage.py runserver

URLの最後にadminをつけます

先ほどスーパーユーザーを作成したIDとパスワードでログインします。

accountsにあるユーザーを開くと、下に先ほど追加した入社日の項目があります!

日時までなっちゃってますね…変えないとですね

入社日をDatetimeField ⇒ DateFieldに変更します

db.sqllite3を削除して、もう一度データベースの作成からしていきます。

python manage.py makemigrations
python manage.py migrate  
python manage.py createsuperuser

もう一度サーバーを起動させます

python manage.py runserver
やったーできた!これをするのに5時間以上かかりました(笑)

Django 動くログイン画面を作ってみた

userを作ったらログイン画面を実装します。

config/settings.pyの編集

AUTH_USER_MODEL = 'accounts.CustomUser'

SESSION_COOKIE_AGE = 7200
SESSION_SAVE_EVERY_REQUEST = True
SESSION_EXPIRE_AT_BROWSER_CLOSE = True

LOGIN_REDIRECT_URL = '/accounts/home'
LOGOUT_REDIRECT_URL = '/accounts/login'
LOGIN_URL = '/accounts/login'


STATIC_URL = '/static/'
STATICFILES_DIRS = (
    os.path.join(BASE_DIR, "static"),
)

MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'

PUBLIC_PATHS = [
   '/accounts/login',  
]
config/urls.py を変更します
from django.contrib import admin
from django.urls import path, include
from django.conf import settings
from django.conf.urls.static import static
from django.views.generic.base import TemplateView

urlpatterns = [
    path('admin/', admin.site.urls),
    path('accounts/', include('accounts.urls')),
    path('', include('accounts.urls')),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)+ static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
これで先ほど作ったaccounts のURLに受け渡されます。
from django.conf.urls import url
from django.contrib.auth import views as auth_views
from . import views
from django.urls import path, include

app_name = 'accounts'

urlpatterns = [
    path('login/', auth_views.LoginView.as_view(template_name='accounts/login.html'), name='login'),
    path('logout/', auth_views.LogoutView.as_view(), name='logout'),
    path('home/', views.home, name="home"),
]
ログインやログアウトは、viewsの呼び出しはなく、templatesを直接呼び出す形になります。
まずは、ログイン時のための画面を作成します。
これで、accounts/home のリクエストがあった場合に、templatesのフォルダのaccountsのフォルダにあるhome.htmlが呼び出されます
WebシステムってURLが何をしなきゃいけないかの指示書みたいなものですね
ログイン用画面はこの記事を採用して、動きを付けたものを実装してみました
Django ログイン画面
画面いっぱいに表示されていますが、スマホで見た時にこの方が見やすいのでこのままいこうと思います(笑)

-Django
-

© 2021 ごろう@縁紡ぐ