#这是v1.5中新增加的功能
#本文由frikyskice 根据官方Docs自行描述,请以原文档为准
#https://docs.djangoproject.com/en/dev/topics/auth/customizing/#substituting-a-custom-user-model
#本文目的给英文不好的筒子们一个参考,不代表其正确性
#frikyskice授权任何个人或组织直接传播本文,但不包括此情况(以本文进行非公益性质的商业盈利)
#本人不专业,拒绝回答技术问题,以免误人误己
通过定义AUTH_USER_MODEL 可对User模型进行自定义扩展
例如:
AUTH_USER_MODEL = 'myapp.MyUser'
扩展的app必须装入INSTALLED_APPS中
如果你已经定义AUTH_USER_MODEL,系统中原有的User模型不能直接使用
以下均以已经定义AUTH_USER_MODEL作为假设
get_user_model()
该函数用以返回正在使用的自定义的User模型(注意不是系统中自带的那个User)
使用方法:
django.contrib.auth.get_user_model()
‘’‘
对于原有的外键及多对多关系,你需要使用宏的模式进行处理,如下:
from django.conf import settings
from django.db import models
class Article(models.Model):
author = models.ForeignKey(settings.AUTH_USER_MODEL)
’‘’
如何自定义你的User模型
自定义User模型需要满足以下基本条件
- 模型必须有一个主键,并且是integer模型(建议不要在此做花样,直接autoXXXX,你懂的)
- 模型必须能有一个字段进行唯一性区分(注意不能是1中的东西),什么字段都可以
- 提供特定的方式以便于程序可以找到这个User(非系统自带),长短两个名称的form(这句大约就是这个意思)#in a “short” and “long” form#
当然这里最简单的方式是直接继承 AbstractBaseUser ,这样上面3个你可以不用管, AbstractBaseUser 就相当于djangoV1.4里面的User,如果你继承 AbstractBaseUser ,需要做以下内容:(我写的好啰嗦…………)
例如:
class MyUser(AbstractBaseUser):
identifier = models.CharField(max_length=40, unique=True, db_index=True)
...
USERNAME_FIELD = 'identifier'
这里注意 identifier 中的unique=True 必须显示的标明,对应上面3条中的二条(麻将?)
例如:
class MyUser(AbstractBaseUser):
...
date_of_birth = models.DateField()
height = models.FloatField()
...
REQUIRED_FIELDS = ['date_of_birth', 'height']
**#这里是一个list,告诉系统那些是必须填的字段**
is_active
AbstractBaseUser 中默认的初始化为True,自己看着办吧
后面就是两函数,对应三条,嗯,你懂得,返回个字符串就行,啥啥的没关系,自己看着办
get_full_name() | get_short_name()
以下为AbstractBaseUser的其他一些方法,同v1.4中的User,不用重载,重载你也不用看我写的了
class models.AbstractBaseUser:
get_username()
is_anonymous()
is_authenticated()
set_password(raw_password)
check_password(raw_password)
set_unusable_password()
has_usable_password()
这里提一下,创建用户模型的时候最好加上username和email两个字段,这样你可以直接使用django自带的UserManager,如果没有,自己写一个吧,基类为 BaseUserManager,
必须提供以下两个方法
def create_user(self, email, date_of_birth, password=None):
# create user here
...
def create_superuser(self, email, date_of_birth, password):
# create superuser here
...
BaseUserManager也提供其他方法,自己查文档,不浪费口水了,当然你可以根据需要自己定义
以下为如何扩展django自己的User模型
如果django自带的User能满足你的要求,你可以简单的继承 django.contrib.auth.models.AbstractUser,并加入自己需要增加的简单字段。
凡是User模型提供的功能,AbstractUser都默认提供。
如果User模型不能满足你的要求,你需要完全自己定义相应的描述,并提供相应的功能来达到你的要求(包括相应的Forms)。
依赖User模型,任何自定义的模型都必须重载
依赖User模型,任何自定义的模型都必须重载
与AbstractBaseUser的子类协同工作,与子类中的USERNAME_FIELD申明的字段相符,就是USERNAME_FIELD定义的啥,依据啥来验证用户
原文举了个例子,自己去看吧,不过和密码相关的几个都不用重载
SetPasswordForm
PasswordChangeForm
AdminPasswordChangeForm
如何定义自定义User的admin功能
必须自己定义一个ModelAdmin的继承至django.contrib.auth.admin.UserAdmin的子类,这个很绕口,不过后面的例子一看就能明白,不做赘述。
由于本文用以扫盲,因此中间有几个话题略过
以下为Docs中的一个完整的例子:
Filenames:models.py
from django.db import models
from django.contrib.auth.models import (
BaseUserManager, AbstractBaseUser
)
class MyUserManager(BaseUserManager):
def create_user(self, email, date_of_birth, password=None):
"""
Creates and saves a User with the given email, date of
birth and password.
"""
if not email:
raise ValueError('Users must have an email address')
user = self.model(
email=MyUserManager.normalize_email(email),
date_of_birth=date_of_birth,
)
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self, email, date_of_birth, password):
"""
Creates and saves a superuser with the given email, date of
birth and password.
"""
user = self.create_user(email,
password=password,
date_of_birth=date_of_birth
)
user.is_admin = True
user.save(using=self._db)
return user
class MyUser(AbstractBaseUser):
email = models.EmailField(
verbose_name='email address',
max_length=
255,
unique=True,
db_index=True,
)
date_of_birth = models.DateField()
is_active = models.BooleanField(default=True)
is_admin = models.BooleanField(default=False)
objects = MyUserManager()
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['date_of_birth']
def get_full_name(self):
# The user is identified by their email address
return self.email
def get_short_name(self):
# The user is identified by their email address
return self.email
def __unicode__(self):
return self.email
def has_perm(self, perm, obj=None):
"Does the user have a specific permission?"
# Simplest possible answer: Yes, always
return True
def has_module_perms(self, app_label):
"Does the user have permissions to view the app `app_label`?"
# Simplest possible answer: Yes, always
return True
@property
def is_staff(self):
"Is the user a member of staff?"
# Simplest possible answer: All admins are staff
return self.is_admin
Filenames:admin.py
from django import forms
from django.contrib import admin
from django.contrib.auth.models import Group
from django.contrib.auth.admin import UserAdmin
from django.contrib.auth.forms import ReadOnlyPasswordHashField
from customauth.models import MyUser
class UserCreationForm(forms.ModelForm):
"""A form for creating new users. Includes all the required
fields, plus a repeated password."""
password1 = forms.CharField(label='Password', widget=forms.PasswordInput)
password2 = forms.CharField(label='Password confirmation', widget=forms.PasswordInput)
class Meta:
model = MyUser
fields = ('email', 'date_of_birth')
def clean_password2(self):
# Check that the two password entries match
password1 = self.cleaned_data.get("password1")
password2 = self.cleaned_data.get("password2")
if password1 and password2 and password1 != password2:
raise forms.ValidationError("Passwords don't match")
return password2
def save(self, commit=True):
# Save the provided password in hashed format
user = super(UserCreationForm, self).save(commit=False)
user.set_password(self.cleaned_data["password1"])
if commit:
user.save()
return user
class UserChangeForm(forms.ModelForm):
"""A form for updating users. Includes all the fields on
the user, but replaces the password field with admin's
password hash display field.
"""
password = ReadOnlyPasswordHashField()
class Meta:
model = MyUser
fields =
['email', 'password', 'date_of_birth', 'is_active', 'is_admin']
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["password"]
class MyUserAdmin(UserAdmin):
# The forms to add and change user instances
form = UserChangeForm
add_form = UserCreationForm
# The fields to be used in displaying the User model.
# These override the definitions on the base UserAdmin
# that reference specific fields on auth.User.
list_display = ('email', 'date_of_birth', 'is_admin')
list_filter = ('is_admin',)
fieldsets = (
(None, {'fields': ('email', 'password')}),
('Personal info', {'fields': ('date_of_birth',)}),
('Permissions', {'fields': ('is_admin',)}),
)
add_fieldsets = (
(None, {
'classes': ('wide',),
'fields': ('email', 'date_of_birth', 'password1', 'password2')}
),
)
search_fields = ('email',)
ordering = ('email',)
filter_horizontal = ()
# Now register the new UserAdmin...
admin.site.register(MyUser, MyUserAdmin)
# ... and, since we're not using Django's builtin permissions,
# unregister the Group model from admin.
admin.site.unregister(Group)
最后,你需要更改settings.py 文件
AUTH_USER_MODEL = 'customauth.MyUser'