Django 自定义用户模型

Django 自定义用户模型

Django自带了一个出色的内置用户模型和身份验证支持。这是大多数开发人员更喜欢Django而不是Flask、FastAPI、AIOHttp和许多其他框架的主要原因。

但是有时候我们对用户模型不满意,或者想根据项目要求进行自定义。假设我们不再需要用户名字段。或者我们想要使用 用户的电子邮件 而不是默认的 用户名 。为了做到这一点,我们需要自定义我们的默认 Django用户 模型。

在本教程中,我们将从头开始构建用户模型。你应该记住的一件事是,自定义Django默认值会给复杂的系统增加很多复杂性。所以尽量使用默认用户模型。但是对于项目要求,我们可以进行默认更改。

我们将使用Django内置的 AbastractBaseClass ,该类由自定义类名称继承。

如果你是Django的新手,请访问我们的 Django教程

先决条件

  • 安装最新的Django(2.2以上)
  • 创建Django项目
  • 进行基本配置
  • 创建虚拟环境

在Django中创建自定义用户模型

我们的第一步是使用以下命令在项目中创建一个应用。

python manage.py startapp MyUserModel

该应用程序将在项目目录中创建。现在将该应用程序注册到settings.py文件中。

MyUserModel/setting.py

INSTALLED_APP = [
?????
?????.
MyUserModel
]

1. 为自定义用户创建模型

现在我们将在models.py文件中创建自定义用户模型。让我们看下面的代码。

from django.db import models
from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin
from django.utils import timezone
from django.utils.translation import gettext_lazy as _
from .managers import CustomUserManager
# Create your models here.

class CustomUser(AbstractBaseUser, PermissionsMixin):
    username = None
    email = models.EmailField(_('email_address'), unique=True, max_length = 200)
    date_joined = models.DateTimeField(default=timezone.now)
    is_staff = models.BooleanField(default=False)
    is_active = models.BooleanField(default=True)



    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = []

    objects = CustomUserManager()

    def has_perm(self, perm, obj=None):
        "Does the user have a specific permission?"
        # Simplest possible answer: Yes, always
        return True

   def is_staff(self):
        "Is the user a member of staff?"
        return self.staff

    @property
    def is_admin(self):
        "Is the user a admin member?"
        return self.admin

    def __str__(self):
        return self.email

让我们理解上述模型;我们创建了一个名为 CustomUser 的类,该类继承了AbstractbaseClass。然后,我们添加了一个字段 email,is_staff,is_active,date_joined

  • username 被设置为none,因为我们想通过唯一的电子邮件ID而不是用户名对用户进行身份验证。
  • is_staff 如果用户允许登录到管理员面板,则返回true。
  • is_active 如果用户当前处于活动状态,则返回true。如果用户不活动,他/她将不允许登录。
  • USERNAME_FIELDS 将User模型的唯一标识定义为email。
  • REQUIRED_FIELDS 在使用 createsuperuser 命令创建 超级用户 时,会提示字段。它必须包括任何不为空的字段。
  • 管理器类对象指定该类的所有对象来自于 CustomeUserManager 。如果用户拥有所有指定的权限,则 has_permission 返回true。

2. 创建模型管理器

Django为用户管理器提供了内置方法。但是,如果我们创建自定义用户模型,我们需要覆盖默认方法。创建一个新的文件managers.py(名称可以不同),并创建用户模型管理器。以下方法由 BaseUserManager 提供。

from django.contrib.auth.base_user import BaseUserManager
from django.utils.translation import ugettext_lazy as _

"""
    Custom user model manager where email is the unique identifiers
    for authentication instead of usernames.
    """


class CustomUserManager(BaseUserManager):
    """
    Custom user model manager where email is the unique identifiers
    for authentication instead of usernames.
    """
    def create_user(self, email, password, **extra_fields):
        """
        Create and save a User with the given email and password.
        """
        if not email:
            raise ValueError(_('The Email must be set'))
        email = self.normalize_email(email)

        user = self.model(email=email, **extra_fields)
        user.set_password(password)
        user.save()
        return user

    def create_superuser(self, email, password, **extra_fields):
        """
        Create and save a SuperUser with the given email and password.
        """
        extra_fields.setdefault('is_staff', True)
        extra_fields.setdefault('is_superuser', True)
        extra_fields.setdefault('is_active', 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)

    def get_full_name(self):
        '''
        Returns 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):
        '''
        Returns the short name for the user.
        '''
        return self.first_name 

我们创建了 CustomManagerClass 继承自BaseUserManager。它提供了以下辅助方法。

  • create_user() 方法创建、保存并返回User。它会自动将电子邮件转换为小写,返回的User对象的is_active属性将被设置为true。
  • create_superuser() 方法将is_staff和is_active设置为True。
  • get_full_name() 返回用户的全名。
  • get_short_name 返回用户的 first_name

3. 将自定义用户注册到setting.py

必须将创建的自定义用户模型注册到setting.py文件中,否则Django将认为它是一个自定义用户模型,并抛出错误。打开setting.py文件并注册自定义用户模型。

AUTH_USER_MODEL = appName.ClassName

在我们的情况下,它将是 –

AUTH _USER_MODEL = MyUserModel.CustomUser

现在我们可以创建并应用迁移,这将创建一个使用自定义用户模型的新数据库。让我们运行以下命令。

python manage.py makemigrations
python manage.py migrate

我们将获得以下迁移文件。

# Generated by Django 3.2.6 on 2021-08-09 19:55

from django.db import migrations, models
import django.utils.timezone

class Migration(migrations.Migration):

    initial = True

    dependencies = [
        ('auth', '0012_alter_user_first_name_max_length'),
    ]

    operations = [
        migrations.CreateModel(
            name='CustomerUser',
            fields=[
                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                ('password', models.CharField(max_length=128, verbose_name='password')),
                ('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last login')),
                ('is_superuser', models.BooleanField(default=False, help_text='Designates that this user has all permissions without explicitly assigning them.', verbose_name='superuser status')),
                ('email', models.EmailField(max_length=254, unique=True, verbose_name='email_address')),
                ('is_staff', models.BooleanField(default=False)),
                ('is_active', models.BooleanField(default=True)),
('groups', models.ManyToManyField(blank=True, help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.', related_name='user_set', related_query_name='user', to='auth.Group', verbose_name='groups')),
                ('user_permissions', models.ManyToManyField(blank=True, help_text='Specific permissions for this user.', related_name='user_set', related_query_name='user', to='auth.Permission', verbose_name='user permissions')),
            ],
            options={
                'abstract': False,
            },
        ),
    ]

正如我们所看到的,由于在创建自定义用户模型时被消除,因此没有用户名字段。

4. 创建超级用户

运行以下命令来创建超级用户。

python manage.py createsuperuser

上述命令将提示输入电子邮件和密码字段以创建超级用户。

Email address: stash
Password:
Password (again):
Superuser created successfully.

创建表单以存储用户信息

我们将使用默认的子类 UserCreationForm 表单来创建一个表单,以便他们可以使用自定义的用户模型。

让我们在”MyUserModel”中创建一个forms.py文件。

forms.py

from django.contrib.auth.forms import UserCreationForm, UserChangeForm
from django.db.models import fields
from django import forms
from .models import CustomerUser
from django.contrib.auth import get_user_model

User = get_user_model()

class CustomUserCreationForm(UserCreationForm):

    password1 = forms.CharField(widget=forms.PasswordInput)
    password2 = forms.CharField(label='Confirm Password', widget=forms.PasswordInput)

    class Meta:
        model = CustomerUser
        fields = ('email', )

    def clean_email(self):
        email = self.cleaned_data.get('email')
        qs = User.objects.filter(email=email)
        if qs.exists():
            raise forms.ValidationError("Email is taken")
        return email

    def clean(self):
        '''
        Verify both passwords match.
        '''
        cleaned_data = super().clean()
        password1 = cleaned_data.get("password1")
        password2 = cleaned_data.get("password2")

        if password1 is not None and password1 != password2:
            self.add_error("password2", "Your passwords must match")
        return cleaned_data

    def save(self, commit=True):
        # Save the provided password in hashed format
        user = super().save(commit=False)
        user.set_password(self.cleaned_data["password1"])
        if commit:
            user.save()
        return user        


class CustomUserChangeForm(UserChangeForm):
    class Meta:
        model = CustomerUser
        fields = ('email', )

    def clean_password(self):
        # Regardless of what the user provides, return the initial value.
        # This is done here, rather than on the field, because the
        # field does not have access to the initial value
        return self.initial["password1"]

CustomUserCreationForm 类继承了 UsecreationForm 类,其中包括三个字段 – username、password1和password2。password1必须与password2匹配,如果两个密码匹配,validate_password()函数将验证密码,并使用 set_password() 设置用户的密码。密码将以散列格式保存。

现在我们将自定义管理面板。

自定义管理面板

默认的管理面板非常有用,可以高效地安排信息,但我们可以根据需要自行进行定制。让我们看看管理面板的以下代码。

admin.py

from django.contrib import admin
from django.contrib.auth import authenticate
from django.contrib.auth.admin import UserAdmin
# Register your models here.
class CustomUserAdmin(UserAdmin):
    add_form = CustomUserCreationForm
    form = CustomUserChangeForm
    model = CustomerUser

    list_display = ('email', 'is_staff', 'is_active',)
    list_filter = ('email', 'is_staff', 'is_active',)
    fieldsets = (
        (None, {'fields': ('email', 'password')}),
        ('Permissions', {'fields': ('is_staff', 'is_active')}),
    )
    add_fieldsets = (
        (None, {
            'classes': ('wide',),
            'fields': ('email', 'password1', 'password2', 'is_staff', 'is_active')}
        ),
    )
    search_fields = ('email',)
    ordering = ('email',)
    filter_horizontal = ()

admin.site.register(CustomerUser, CustomUserAdmin)

现在我们已经准备好创建新用户了。运行以下命令,并使用超级用户凭据登录到管理员面板。
Django 自定义用户模型

一旦我们登陆管理员面板。我们会看到 添加自定义用户 按钮,用于创建新用户。

Django 自定义用户模型

创建一些用户之后,管理员面板将如下所示。

Django 自定义用户模型

结论

Django因其内置的功能而受欢迎,可以节省开发人员的大量时间。但有时我们需要一些内置模型中没有的功能。不过,我们可以按照自己的方式创建它们。在本教程中,我们通过扩展AbstractBaseClass创建了自定义用户模型。我们创建了管理器类来管理用户对象。您可以借助本教程创建一个新的自定义用户模型。您可以为用户提供更多权限,并使用户模型具有丰富的功能。

Camera课程

Python教程

Java教程

Web教程

数据库教程

图形图像教程

办公软件教程

Linux教程

计算机教程

大数据教程

开发工具教程