2023年7月更新:
你可以使用
电子邮件
和
密码
来设置身份验证,而不是
用户名
和
密码
。在这个说明中,
用户名
被移除了,并且我尽量不改变
Django的默认设置。*你还可以查看
我的答案,解释如何通过
OneToOneField()扩展
用户模型以添加额外的字段,以及查看
我的答案和
我的答案,解释
AbstractUser和
AbstractBaseUser之间的区别。
首先,运行下面的命令来创建
account
应用程序:
python manage.py startapp account
然后,将
account
应用程序设置为
INSTALLED_APPS,并在
settings.py
中设置
AUTH_USER_MODEL = 'account.User',如下所示:
INSTALLED_APPS = [
...
"account",
]
AUTH_USER_MODEL = 'account.User'
然后,在
account
文件夹下创建
managers.py
,并在
managers.py
中创建一个继承
(UM)UserManager的
UserManager
类,如下所示。*只需将下面的代码复制粘贴到
managers.py
中,并且
managers.py
是必要的,以使命令
python manage.py createsuperuser
正常工作,不会出现任何错误:
from django.contrib.auth.models import UserManager as UM
from django.contrib.auth.hashers import make_password
class UserManager(UM):
def _create_user(self, email, password, **extra_fields):
if not email:
raise ValueError("The given email must be set")
email = self.normalize_email(email)
user = self.model(email=email, **extra_fields)
user.password = make_password(password)
user.save(using=self._db)
return user
def create_user(self, email=None, password=None, **extra_fields):
extra_fields.setdefault("is_staff", False)
extra_fields.setdefault("is_superuser", False)
return self._create_user(email, password, **extra_fields)
def create_superuser(self, email=None, password=None, **extra_fields):
extra_fields.setdefault("is_staff", True)
extra_fields.setdefault("is_superuser", True)
if extra_fields.get("is_staff") is not True:
raise ValueError("Superuser must have is_staff=True.")
if extra_fields.get("is_superuser") is not True:
raise ValueError("Superuser must have is_superuser=True.")
return self._create_user(email, password, **extra_fields)
然后,创建一个扩展
AbstractUser的
User
模型,并通过将其设置为
None
来移除
username
,并使用
unique=True设置
email
,将
email
设置为
USERNAME_FIELD,并在
account/models.py
中将
UserManager
设置为
objects
,如下所示。*只需将下面的代码
复制并粘贴到
account/models.py
中:
from django.db import models
from django.utils.translation import gettext_lazy as _
from django.contrib.auth.models import AbstractUser
from .managers import UserManager
class User(AbstractUser):
username = None
email = models.EmailField(_("email address"), unique=True)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = []
objects = UserManager()
或者,您还可以创建一个扩展
AbstractBaseUser和
PermissionsMixin的
User
模型,如下所示。*下面的代码与使用
AbstractUser
的代码等效:
from django.db import models
from django.utils.translation import gettext_lazy as _
from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin
from django.utils import timezone
from .managers import UserManager
class User(AbstractBaseUser, PermissionsMixin):
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"), unique=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)
USERNAME_FIELD = 'email'
objects = UserManager()
class Meta:
verbose_name = _("user")
verbose_name_plural = _("users")
*不要像下面这样扩展
DefaultUser(User)模型,否则会出错:
from django.contrib.auth.models import User as DefaultUser
class User(DefaultUser):
...
然后,在
account/admin.py
中创建一个继承
UA(UserAdmin)的
UserAdmin
类,如下所示。*只需将下面的代码
复制并粘贴到
account/admin.py
中:
from django.contrib import admin
from django.utils.translation import gettext_lazy as _
from django.contrib.auth.admin import UserAdmin as UA
from .models import User
@admin.register(User)
class UserAdmin(UA):
fieldsets = (
(None, {"fields": ("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": ("email", "password1", "password2"),
},
),
)
list_display = ("email", "first_name", "last_name", "is_staff")
ordering = ("-is_staff",)
readonly_fields=('last_login', 'date_joined')
然后,运行以下命令。*在定制
User
模型时,这必须是对数据库的第一次迁移,否则根据我的实验和
文档会出现错误,所以在开发Django项目之前,您必须先创建自定义的
User
模型:
python manage.py makemigrations && python manage.py migrate
然后,运行以下命令:
python manage.py createsuperuser
然后,运行以下命令:
python manage.py runserver 0.0.0.0:8000
然后,打开下面的网址:
http://localhost:8000/admin/login/
最后,您可以使用如下所示的电子邮件
和密码
进行登录:
![enter image description here](https://istack.dev59.com/eNKms.webp)
而且,这是如下所示的 自定义用户添加 页面:
![enter image description here](https://istack.dev59.com/ZNlto.webp)
if user.check_password(password):
,你可能想要包括Django自带的默认操作ModelBackend
:if user.check_password(password) and self.user_can_authenticate(user):
,以便检查用户是否具有is_active=True
。 - jmq