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')
我已经按照您的要求进行了定制。
请查看
有关自定义admin.ModelAdmin(UserAdmin的超类)的信息,请参考此条目。
Django管理界面反向檢索筆記