Django2.0の公式ドキュメントで確認すると、
ログイン認証で使われているUSERというモデルはデフォルトで使うべきでなく、
カスタムして利用することを勧めているようだ。
せっかくなので、AbstractBaseUserを使用して
カスタムを試みたら、いつの間にかログイン認証もカスタマイズしてしまった。
ログイン認証で使用するモデルをCustomUserとし、
USERで定義されている変数に加えて、住所情報等を加える。
もっと簡単な方法も存在するが、
AbstractBaseUserを使ったカスタマイズが自由度が高いため、
こちらを使用した。
ディレクトリ構造は以下の通り
(当記事の説明ため、必要最低限のみ記載)
project/
app/
models.py
views.py
auth.py
・・・
project/
settings.py
・・・
# project/app/model.py from django.contrib.auth.models import AbstractBaseUser, UserManager class CustomUser(AbstractBaseUser): userno = models.IntegerField(unique=True) username = models.CharField(max_length=30, unique=True) password = models.CharField(max_length=256) first_name = models.CharField(max_length=30, null=True, blank=True) last_name = models.CharField(max_length=30, null=True, blank=True) email = models.CharField(max_length=256, null=True, blank=True) postcd = models.CharField(max_length=8, null=True, blank=True) address1 = models.CharField(max_length=48, null=True, blank=True) address2 = models.CharField(max_length=48, null=True, blank=True) address3 = models.CharField(max_length=48, null=True, blank=True) telephone = models.CharField(max_length=15, null=True, blank=True) enabled = models.CharField(max_length=1) reguserno = models.IntegerField() regdate = models.DateTimeField() moduserno = models.IntegerField(null=True, blank=True) moddate = models.DateTimeField(null=True, blank=True) USERNAME_FIELD = 'username' objects = UserManager() class Meta: db_table = 'CustomUser' swappable = 'AUTH_USER_MODEL'
次にsettings.pyに以下を修正・追記する。
# project/project/settings.py ## 修正 INSTALLED_APPS = [ # 'django.contrib.admin', //コメントアウト ## 追記 AUTH_USER_MODEL = 'app.CustomUser'
AUTH_USER_MODELについては、ディレクトリ構造から、'app.models.CustomUser'が正しいと思っていたが、調べてみる限り、'app.CustomUser'が正しいみたいだ。
'django.contrib.admin'をコメントアウトにした理由は、
マイグレーション作成時に以下のエラーが発生したためである。
project> python manage.py makemigrations SystemCheckError: System check identified some issues: ERRORS: <class 'django.contrib.auth.admin.UserAdmin'>: (admin.E019) The value of 'filter_horizontal[0]' refers to 'groups', which is not an attribute of 'app.CRI_M_USER'. <class 'django.contrib.auth.admin.UserAdmin'>: (admin.E019) The value of 'filter_horizontal[1]' refers to 'user_permissions', which is not an attribute of 'app.CRI_M_USER'. <class 'django.contrib.auth.admin.UserAdmin'>: (admin.E108) The value of 'list_display[4]' refers to 'is_staff', which is not a callable, an attribute of 'UserAdmin', or an attribute or method on 'app.CRI_M_USER'. <class 'django.contrib.auth.admin.UserAdmin'>: (admin.E116) The value of 'list_filter[0]' refers to 'is_staff', which does not refer to a Field. <class 'django.contrib.auth.admin.UserAdmin'>: (admin.E116) The value of 'list_filter[1]' refers to 'is_superuser', which does not refer to a Field. <class 'django.contrib.auth.admin.UserAdmin'>: (admin.E116) The value of 'list_filter[2]' refers to 'is_active', which does not refer to a Field. <class 'django.contrib.auth.admin.UserAdmin'>: (admin.E116) The value of 'list_filter[3]' refers to 'groups', which does not refer to a Field.
つまり、CustomUserにはis_staffやis_activeの変数が存在しないことを示している。
本来はそれらも定義するべきであったが、より簡単な認証方法にしたかった。
そのため、'django.contrib.admin'をコメントアウトにした。
これにより、Djangoデフォルトで用意されている管理者サイトは使えない。
そうなると、ログイン認証もいつも通りの方法でエラーが発生しかねない可能性があったため、
ログイン認証もカスタマイズしようという判断に至った。
# project/app/views.py from app.auth import * def Logout(request): auth_logout(request) return redirect("app:login") def Login(request): if request.method == 'POST': username = request.POST['username'] password = request.POST['password'] user = authenticate(request, username, password) if user is not None: return redirect("app:toppage") else: return render(request, 'login.html', { 'msg': u'ユーザID、あるいはパスワードが一致しません。', 'username': '', 'password': ''}) else: return render(request, 'login.html', { 'msg': '', 'username': '', 'password': '' })
# project/app/auth.py from django.contrib.auth import login, logout from app.models import * import hashlib def authenticate(request, username=None, password=None): user = None try: user = CustomUser.objects.get(username=username) except CustomUser.DoesNotExist: return None if user.password == createPassword(password): login(request, user) return user return None def createPassword(str): salt = '************' str = salt + str for i in range(1000): str = hashlib.sha256(str.encode('utf-8')).hexdigest() return str def auth_logout(request): logout(request) return
Comment
現在、コメントはありません。