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
現在、コメントはありません。