创建、注册、登录和注销Django自定义用户的功能(基于函数)
Table of Contents
用户模型创建
用户注册
用户登录
用户退出
创建用户模型
创建一个名为「accounts」的应用程序,并在「models.py」中定义Users模型。
导入两个模块:django.contrib.auth.models中的AbstractBaseUser和PermissionsMixin。
使Users模型继承AbstractBaseUser和PermissionsMixin。
- AbstractBaseUser是一个只定义用户认证功能的类。
- PermissionsMixin是一个定义了超级用户权限等的类。
from django.db import models
from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin
from django.contrib.auth.models import UserManager
class Users(AbstractBaseUser, PermissionsMixin):
username = models.CharField(max_length=255)
email = models.EmailField(max_length=255, unique=True)
icon = models.FileField(null=True, upload_to='icon/')
is_staff = models.BooleanField(default=False)
objects = UserManager()
USERNAME_FIELD = 'email' #ユーザーを一意に識別する
REQUIRED_FIELDS = ['username'] # スーパーユーザーに名前を持たせる
class Meta:
db_table = 'users' #テーブル名を指定
通过使用USERNAME_FIELD = ’email’,可以将电子邮件用作认证。
默认情况下,Django会使用自带的用户模型,所以要使用自定义用户模型,需要在「settings.py」中定义AUTH_USER_MODEL,并指定创建的Users模型。
AUTH_USER_MODEL = 'accounts.Users'
在进行迁移之前,请设置AUTH_USER_MODEL选项。一旦设置完成,就可以进行迁移了。
python manage.py makemigrations accounts
python manage.py migrate
用户注册
我会创建一个用于用户注册的表单。
在accounts文件夹中创建一个新的”forms.py”文件。
导入”models.py”中创建的Users和validate_password来进行密码验证。
from django import forms
from django.contrib.auth.password_validation import validate_password
from .models import Users
class SignInForm(forms.ModelForm):
username = forms.CharField(label="名前")
email = forms.EmailField(label='メールアドレス')
password = forms.CharField(label='パスワード', widget=forms.PasswordInput)
confirm_password = forms.CharField(label='パスワード再入力', widget=forms.PasswordInput)
class Meta:
model = Users
fields = ('username', 'email', 'password')
def clean(self):
cleaned_data = super().clean()
password = cleaned_data.get('password')
confirm_password = cleaned_data.get('confirm_password')
if password != confirm_password:
raise forms.ValidationError('パスワードが一致しません。')
def save(self):
user = super().save(commit=False)
validate_password(self.cleaned_data.get('password'), user)
user.set_password(self.cleaned_data.get('password'))
user.save()
return user
通过继承forms.ModelForm,可以使用save()方法将表单内容保存到数据库中。
通过将password和confirm_password指定为widget=forms.PasswordInput,可以创建用于输入密码的表单。另外,通过confirm_password要求用户再次输入密码,以预防密码输入错误的情况。
类元
在Meta类中用model=Users指定要注册表单内容的模型,并用fields指定要注册的字段(确认密码不会被注册到数据库中,因此被省略)。
清除方法
clean()方法会检查password和confirm_password是否匹配,如果不匹配,则返回验证错误。
cleaned_data = super()。clean()将输入的值从表单中取出,并存储在cleaned_data中。(super()指的是父类,在这种情况下指的是SignInForm)
# super().clean()により取得した値
{'username': 'test', 'email': 'test@example.com', 'password': 'noteapppass', 'confirm_password': 'noteapppass'}
将密码(password)和确认密码(confirm_password)作为cleaned_data.get(‘字段名’)的方式分别提取出来。
保存方法
为了避免默认的save方法导致密码以明文形式保存,我们需要重写save方法,将密码进行加密后再保存。
通过使用super().save(commit=False),我们可以获取表单的值(通过commit=False,可以仅获取值而不保存到数据库)。
使用validate_password对密码进行验证。
使用user.set_password方法对密码进行加密,然后使用user().save()保存到数据库中。
创建用户注册视图
在「accounts」文件夹的「views.py」中添加用户注册的处理。
从django.shortcuts导入render、redirect ←添加redirect
从django.core.exceptions导入ValidationError
从.导入forms
在render后面添加redirect,并添加用于异常处理的ValidationError,最后导入form。
from django.shortcuts import render, redirect, get_object_or_404
from django.core.exceptions import ValidationError
from . import forms
def signin(request):
signin_form = forms.SignInForm(request.POST or None)
if signin_form.is_valid():
try:
signin_form.save()
return redirect('accounts:home')
except ValidationError as e:
signin_form.add_error('password', e)
return render(request,'accounts/signin.html', context={
'signin_form': signin_form,
})
在使用 POST 方法发送的数据中,通过 request.POST 接收数据,如果是 GET 方法,则返回 None。
通过 signin_form.is_valid() 进行验证检查,并执行在表单中定义的 clean 方法。
通过try语句来执行异常处理,并使用signin_form.save()来执行form中定义的save方法。此时,如果在SignInForm中定义的save方法的validate_password中出现验证错误,那么会调用except部分并通过signin_form.add_error(‘password’, e)将错误传递给表单的password字段。
如果完全实现,则使用重定向进行转移。
登录
创建登录表单
在「accounts」文件夹的「forms.py」中添加一个用于登录的表单。
class LoginForm(forms.Form):
email = forms.EmailField(label="メールアドレス")
password = forms.CharField(label="パスワード", widget=forms.PasswordInput)
在登录表单中,我们不会将数据保存到数据库,因此我们继承了forms.Form。
由于本次登录要使用电子邮件地址,所以我们定义了电子邮件地址和密码的字段。
创建登录视图
从django.contrib.auth中导入authenticate和login函数,从django.contrib中导入messages模块。
authenticate函数用于对用户进行身份验证,login函数用于执行登录操作。
messages模块用于在登录后或登录失败时显示消息。
from django.contrib.auth import authenticate, login
def user_login(request):
login_form = forms.LoginForm(request.POST or None)
if login_form.is_valid():
email = login_form.cleaned_data.get('email')
password = login_form.cleaned_data.get('password')
user = authenticate(email=email, password=password)
if user:
login(request, user)
messages.success(request, 'ログインしました。')
return redirect('accounts:home')
else:
message.warning(request, 'メールアドレスかパスワードが間違っています。')
return render(request, 'accounts/login.html', context={
'login_form': login_form,
})
user = authenticate(email=email, password=password)
if user is not None:
login(request, user)
messages.success(request, ‘ログインしました。’)
<div class="message">
{% if messages %}
{% for message in messages %}
<div class="alert alert-{{ message.tags }}">
{{ message.message }}
</div>
{% endfor %}
{% endif %}
</div>

退出登录
创建用于登出的视图
从django.contrib.auth导入authenticate,login,logout ⬅︎ 添加logout
从django.contrib.auth.decorators导入login_required
login_required用于判断用户是否已登录。作为logout函数的修饰符,如果用户未登录,则不执行函数。
from django.contrib.auth import authenticate, login, logout
from django.contrib.auth.decorators import login_required
@login_required
def user_logout(request):
logout(request)
messages.success(request, 'ログアウトしました。')
return redirect('accounts:home')
通过`logout(request)`来执行注销操作。