自動化無しに生活無し

WEBとかAIとかLinux関係をひたすら書く備忘録系ブログ

【Django】allauthとカスタムユーザーモデルを実装した簡易掲示板を作る【AbstrastBaseUser】

thumbnail

手元のディレクトリ内で雛形が分散していたので、自分用に作った。

コードは40分Django簡易掲示板から。allauthはsettings.pyにID認証を、ユーザーモデルはDjangoのGitHubから何も書き加えていないモデルをそのまま流用した。

以前はfirst_nameとlast_nameを1つのhandle_nameにしたが、今回は元に戻した。

雛形をすぐにDLして書き換えができるようにGitHubに公開する。

usersアプリを作成

python3 manage.py startapp users

users/models.py

ほぼ流用。handle_nameは元のfirst_nameとlast_nameに分割

from django.db import models

from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin, UserManager
from django.contrib.auth.validators import UnicodeUsernameValidator

from django.utils import timezone

from django.utils.translation import gettext_lazy as _
from django.core.mail import send_mail

import uuid


#ここ( https://github.com/django/django/blob/main/django/contrib/auth/models.py#L334 )から流用
class CustomUser(AbstractBaseUser, PermissionsMixin):

    username_validator  = UnicodeUsernameValidator()

    id          = models.UUIDField( default=uuid.uuid4, primary_key=True, editable=False )
    username    = models.CharField(
                    _('username'),
                    max_length=150,
                    unique=True,
                    help_text=_('Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.'),
                    validators=[username_validator],
                    error_messages={
                        'unique': _("A user with that username already exists."),
                    },
                )

    first_name  = models.CharField(_('first name'), max_length=150, blank=True)
    last_name   = models.CharField(_('last name'), max_length=150, blank=True)

    email       = models.EmailField(_('email address'), blank=True)

    is_staff    = models.BooleanField(
                    _('staff status'),
                    default=False,
                    help_text=_('Designates whether the user can log into this admin site.'),
                )

    is_active   = models.BooleanField(
                    _('active'),
                    default=True,
                    help_text=_(
                        'Designates whether this user should be treated as active. '
                        'Unselect this instead of deleting accounts.'
                    ),
                )
    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 #←このabstractをコメントアウトする

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

    def get_full_name(self):
        """
        Return the first_name plus the last_name, with a space in between.
        """
        full_name = '%s %s' % (self.first_name, self.last_name)
        return full_name.strip()

    def get_short_name(self):
        """Return the short name for the user."""
        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)

users/forms.py

from django.contrib.auth.forms import UserCreationForm
from .models import CustomUser

class SignupForm(UserCreationForm):
    class Meta(UserCreationForm.Meta):
        model   = CustomUser
        fields  = ("username", )

会員登録時に入力するのはデフォルトのユーザーネームのみ。

デフォルトの状態で、会員登録時に使用するフォームクラス、UserCreationFormを継承して作る。

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 CustomUser

class CustomUserAdmin(UserAdmin):

    fieldsets = (
        (None, {'fields': ('username', 'password')}),
        (_('Personal info'), {'fields': ('first_name', 'last_name', 'email')}),
        (_('Permissions'), {'fields': ('is_active', 'is_staff', 'is_superuser', 'groups', 'user_permissions')}),
        (_('Important dates'), {'fields': ('last_login', 'date_joined')}),
    )

    #管理サイトから追加するときのフォーム
    add_fieldsets = (
        (None, {
            'classes': ('wide',),
            'fields': ('username', 'password1', 'password2'),
        }),
    )


    list_display = ('username', 'email', 'first_name', 'last_name', 'is_staff')
    search_fields = ('username', 'first_name', 'last_name', 'email')

admin.site.register(CustomUser, CustomUserAdmin)

UserAdminを継承して作る

こちらもHandle_nameはfirst_nameとlast_nameに分割して、元に戻した。

config/settings.py

最後に、settings.pyにてカスタムユーザーモデルを読み込みする設定を施す。

INSTALLED_APPS = [ 

    #==中略==

    'users.apps.UsersConfig',
]
AUTH_USER_MODEL = 'users.CustomUser'
ACCOUNT_FORMS   = { "signup":"users.forms.SignupForm"}

AUTH_USER_MODELは認証時に使用するユーザーモデル

ACCOUNT_FORMSはアカウント新規作成時のフォームを指定しておく。

結論

allauthもsettings.pyにID認証で書き込んでいるだけなので、後はLoginRequiredMixinをビュークラスの引数に追加したり、1対多や多対多のリレーションを組んで、書き込みにユーザー名を表記させたり、投稿に対するコメントを実装させれば良いでしょう。

もし、このコードにSendgridを使用したメール送信機能を実装させたい場合は下記記事を参照。

【Django】allauthを使用し、カスタムユーザーモデルを搭載させ、SendgridのAPIでメール認証をする簡易掲示板【保存版】

全体のソースコード

https://github.com/seiya0723/startup_bbs_custom_usermodel_allauth

スポンサーリンク

シェアボタン

Twitter LINEで送る Facebook はてなブログ