创建一个自定义的Django用户模型(2)

最后编辑于 02月08日 开发

上文见:
创建一个自定义的Django用户模型(1)

Settings
把下面这一行添加到settings.py中,以使Django使用新的用户类:

AUTH_USER_MODEL = 'users.CustomUser'

现在,可以创建和应用迁移了,这将创建使用自定义用户模型的新数据库。在开始之前,我们不用创建迁移文件而可以看一下迁移实际上是什么样子,使用--dry-run标志:

(django-custom-user-model)$ python manage.py makemigrations --dry-run --verbosity 3

运行后会看到类似这样的:

# Generated by Django 2.1.5 on 2019-02-06 14:24

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


class Migration(migrations.Migration):

    initial = True

    dependencies = [
        ('auth', '0009_alter_user_last_name_max_length'),
    ]

    operations = [
        migrations.CreateModel(
            name='CustomUser',
            fields=[
                ('id', models.AutoField(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')),
                ('first_name', models.CharField(blank=True, max_length=30, verbose_name='first name')),
                ('last_name', models.CharField(blank=True, max_length=150, verbose_name='last name')),
                ('is_staff', models.BooleanField(default=False, help_text='Designates whether the user can log into this admin site.', verbose_name='staff status')),
                ('is_active', models.BooleanField(default=True, help_text='Designates whether this user should be treated as active. Unselect this instead of deleting accounts.', verbose_name='active')),
                ('date_joined', models.DateTimeField(default=django.utils.timezone.now, verbose_name='date joined')),
                ('email', models.EmailField(max_length=254, unique=True, verbose_name='email address')),
                ('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={
                'verbose_name': 'user',
                'verbose_name_plural': 'users',
                'abstract': False,
            },
        ),
    ]

开始创建和应用迁移,要确保迁移不包含username字段:

(django-custom-user-model)$ python manage.py makemigrations
(django-custom-user-model)$ python manage.py migrate

看看数据库的schema:

$ sqlite3 db.sqlite3

SQLite version 3.16.0 2016-11-04 19:09:39
Enter ".help" for usage hints.

sqlite> .tables

auth_group                         django_migrations
auth_group_permissions             django_session
auth_permission                    users_customuser
django_admin_log                   users_customuser_groups
django_content_type                users_customuser_user_permissions

sqlite> .schema users_customuser

CREATE TABLE "users_customuser" (
  "id" integer NOT NULL PRIMARY KEY AUTOINCREMENT,
  "password" varchar(128) NOT NULL,
  "last_login" datetime NULL,
  "is_superuser" bool NOT NULL,
  "first_name" varchar(30) NOT NULL,
  "last_name" varchar(150) NOT NULL,
  "is_staff" bool NOT NULL,
  "is_active" bool NOT NULL,
  "date_joined" datetime NOT NULL,
  "email" varchar(254) NOT NULL UNIQUE
);

现在可以使用get_user_model()或settings.AUTH_USER_MODEL引用这个自定义用户模型了。详细信息可参阅官方文档中的引用用户模型,Referencing the User model

此外,在创建超级用户时,系统会提示您输入电子邮件而不是用户名:

(django-custom-user-model)$ python manage.py createsuperuser
Email address: test@test.com
Password:
Password (again):
Superuser created successfully.

现在要确保tests可以通过了:

----------------------------------------------------------------------
Ran 2 tests in 0.282s

OK

Forms
现在,创建可以使用CustomUser模型的UserCreationForm和UserChangeForm的表单子类。
在users目录下创建一个forms.py文件:

from django.contrib.auth.forms import UserCreationForm, UserChangeForm

from .models import CustomUser


class CustomUserCreationForm(UserCreationForm):

    class Meta(UserCreationForm):
        model = CustomUser
        fields = ('email',)


class CustomUserChangeForm(UserChangeForm):

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

Admin
在users/admin.py中创建可以使用上面表单的UserAdmin子类:

from django.contrib import admin
from django.contrib.auth.admin import UserAdmin

from .forms import CustomUserCreationForm, CustomUserChangeForm
from .models import CustomUser


class CustomUserAdmin(UserAdmin):
    add_form = CustomUserCreationForm
    form = CustomUserChangeForm
    model = CustomUser
    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',)


admin.site.register(CustomUser, CustomUserAdmin)

现在运行server,登录到管理页面可以添加和修改用户了:

Michael Herman是一名软件工程师,也是Real Python的联合创始人和作者。

Michael Herman的个人网站:
https://mherman.org/

Real Python:
https://realpython.com/

Michael Herman的文章:
https://testdriven.io/blog/django-custom-user-model/

登录注册后才能评论。