Django 用户自定义方式

关于这篇文章

我总结了关于Django用户自定义的方法。这些内容可以在官方网站找到。
https://docs.djangoproject.com/ja/2.0/topics/auth/customizing/#using-a-custom-user-model-when-starting-a-project

根据这篇文章所指出的,我认为在Django中,基本上应该使用定制化的User。
参考:在Django中应始终使用自定义的User。

Django 2.0.1的版本

定制方式

我們基本上遵循以下的作業步驟。

1. 创建一个名为 “users” 的应用程序。
2. 在 “users.models” 中创建一个继承自 “AbstractBaseUser” 的 “User” 类。
3. 在 “users.admin” 中创建一个继承自 “UserAdmin” 的类。
4. 在配置文件中定义 “AUTH_USER_MODEL = ‘users.User'”。
5. 检查对 “django.contrib.admin” 和 “django.contrib.auth” 的影响范围,并根据需要继承或修改其他类。

将应用程序分离出来,可以获得在其他项目中进行再利用的优势,同时还能对应用程序单独进行转储文件操作。

「users」是cookiecutter-django中也使用的名称。我认为在这里统一使用这个名称是很好的选择。
参考:尝试使用cookiecutter-django

摘要用户还是抽象基本用户?

在定制用户模型的方式中,可以选择继承AbstractUser或者继承AbstractBaseUser。

AbstractUser是AbstractBaseUser抽象类的一个实现。
基于AbstractUser进行定制的话,虽然灵活性较低,但编码量较少;而使用AbstractBaseUser,则灵活性较高,但编码量较大。

在仅需要添加或修改属性的自定义内容时,建议使用AbstractUser;而当需要删除属性或无法满足AbstractUser的自定义时,建议使用AbstractBaseUser。

然而,这只是我的个人看法,我认为在任何情况下都应该使用AbstractBaseUser。原因有以下三点。

・AbstractBaseUser更加具有弹性。
・由于代码不分散,修改时很容易知道修正的位置。
・如果不使用默认属性(如:first_name、last_name、email),可以立即删除。

搜索关键词「AbstractUser vs AbstractBaseUser」会出现许多不同的思考。请选择适合自己的方法。

示例代码

作为练习,我们将尝试根据可能存在的需求进行定制。

・将id更改为UUID
・删除first_name和last_name,并添加full_name
・添加所属(department)。使其能够兼任NxN关系。

在这个页面中介绍了将登录ID更改为电子邮件地址的变更。
在narito博客的Django中,对用户模型进行自定义(继承)。


INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'users',
]

# Application definition
AUTH_USER_MODEL = 'users.User'


from django.db import models
from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin, UserManager
from django.contrib.auth.validators import UnicodeUsernameValidator
from django.utils import timezone
from django.utils.translation import gettext_lazy as _
from django.core.mail import send_mail
import uuid as uuid_lib

# Create your models here.


class Department(models.Model):
    """所属 兼任可"""

    name = models.CharField(_('所属'), max_length=150, blank=True)

    def __str__(self):
        return self.name

    class Meta:
        verbose_name = _('所属')
        verbose_name_plural = _('所属')


class User(AbstractBaseUser, PermissionsMixin):
    """ユーザー AbstractUserをコピペし編集"""

    uuid = models.UUIDField(default=uuid_lib.uuid4,
                            primary_key=True, editable=False)
    username_validator = UnicodeUsernameValidator()

    username = models.CharField(
        _('username'),
        max_length=150,
        unique=True,
        help_text=_(
            'Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.'),
        validators=[username_validator],
        error_messages={
            'unique': _("A user with that username already exists."),
        },
    )
    full_name = models.CharField(_('氏名'), max_length=150, blank=True)
    email = models.EmailField(_('email address'), blank=True)
    departments = models.ManyToManyField(
        Department,
        verbose_name=_('所属'),
        blank=True,
        help_text=_('Specific Departments for this user.'),
        related_name="user_set",
        related_query_name="user",
    )

    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)

    objects = UserManager()

    EMAIL_FIELD = 'email'
    USERNAME_FIELD = 'username'
    REQUIRED_FIELDS = ['email', ]

    class Meta:
        verbose_name = _('user')
        verbose_name_plural = _('users')

    def clean(self):
        super().clean()
        self.email = self.__class__.objects.normalize_email(self.email)

    def email_user(self, subject, message, from_email=None, **kwargs):
        """Send an email to this user."""
        send_mail(subject, message, from_email, [self.email], **kwargs)

    # 既存メソッドの変更
    def get_full_name(self):
        return self.full_name

    def get_short_name(self):
        return self.full_name


from .models import User, Department
from django.contrib.auth.admin import UserAdmin
from django.contrib import admin
from django.utils.translation import gettext, gettext_lazy as _

# Register your models here.
@admin.register(Department)
class AdminDepartment(admin.ModelAdmin):
    pass

@admin.register(User)
class AdminUserAdmin(UserAdmin):

    fieldsets = (
        (None, {'fields': ('username', 'password')}),
        (_('Personal info'), {'fields': ('full_name', 'email','departments')}),
        (_('Permissions'), {'fields': ('is_active', 'is_staff', 'is_superuser',
                                       'groups', 'user_permissions')}),
        (_('Important dates'), {'fields': ('last_login', 'date_joined')}),
    )
    list_display = ('username', 'email', 'full_name', 'is_staff')
    search_fields = ('username', 'full_name', 'email')
    filter_horizontal = ('groups', 'user_permissions','departments')


我已经按照您的要求进行了定制。

image.png

请查看

有关自定义admin.ModelAdmin(UserAdmin的超类)的信息,请参考此条目。

Django管理界面反向檢索筆記

广告
将在 10 秒后关闭
bannerAds