Django自带的用户认证
以前都是用Django自带的用户认证,用户名字段一对一关系对应Django--User表(其实它也是继承了abstractbaseuser)。
1
2
3
|
from
django.contrib.auth.models
import
User
class
UserInfo(models.Model):
username
=
models.OneToOneField(User)
|
为什么使用要自定义用户认证?
原生的Django--User认证只有用户名和密码字段,自定义用户认证可以根据项目的需求定制化和扩展认证系统。
比如把唯一标识改成email,或加入用户组等等。
官方说明
官方文档:
Specifying a custom User
model(指定自定义用户模型)
使用Django自定义用户模型必须满足:
模型必须有一个唯一的字段,可用于识别目的。
用户给定名称为“短”的标识,用户的全名为“长”标识符。他们可以返回完全相同的值。
构建一个符合用户自定义模型的最简单的方法是继承abstractbaseuser类。abstractbaseuser提供一个用户模型的核心实现,包括密码和符号密码重置。Django自带用用户认证User也是继承了它。一些关键的实现细节:
class models.
CustomUser
USERNAME_FIELD
必须有一个唯一标识--USERNAME_FIELD
1
2
3
4
|
class
MyUser(AbstractBaseUser):
name
=
models.CharField(max_length
=
40
, unique
=
True
)
...
USERNAME_FIELD
=
'name'
|
REQUIRED_FIELDS
创建superuser时的必须字段
1
2
3
4
5
6
|
class
MyUser(AbstractBaseUser):
...
date_of_birth
=
models.DateField()
height
=
models.FloatField()
...
REQUIRED_FIELDS
=
[
'date_of_birth'
,
'height'
]
|
abstractbaseuser提供的方法
is_active(),
is_authenticated
()......
自定义models(略)
settings中添加models文件名
1
|
AUTH_USER_MODEL
=
'app.MyUser(类名)'
|
Django会去models中找这个类,所以要在原生的models.py中导入这个类。
代码实现
asset\user_models.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
|
#!/usr/bin/env python
# -*- coding:utf-8 -*-
from
django.db
import
models
from
django.contrib.auth.models
import
(
BaseUserManager, AbstractBaseUser
)
class
UserProfileManager(BaseUserManager):
def
create_user(
self
, email, name, password
=
None
):
"""
Creates and saves a User with the given email, name and password.
"""
'''email是唯一标识,没有会报错'''
if
not
email:
raise
ValueError(
'Users must have an email address'
)
user
=
self
.model(
email
=
self
.normalize_email(email),
name
=
name,
)
user.set_password(password)
#检测密码合理性
user.save(using
=
self
._db)
#保存密码
return
user
def
create_superuser(
self
, email, name, password):
"""
Creates and saves a superuser with the given email, name and password.
"""
user
=
self
.create_user(email,
password
=
password,
name
=
name
)
user.is_admin
=
True
#比创建用户多的一个字段
user.save(using
=
self
._db)
return
user
class
UserProfile(AbstractBaseUser):
email
=
models.EmailField(
verbose_name
=
'email address'
,
max_length
=
255
,
unique
=
True
,
)
name
=
models.CharField(max_length
=
32
)
is_active
=
models.BooleanField(default
=
True
)
is_admin
=
models.BooleanField(default
=
False
)
objects
=
UserProfileManager()
#创建用户
USERNAME_FIELD
=
'email'
REQUIRED_FIELDS
=
[
'name'
]
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
__str__(
self
):
# __unicode__ on Python 2
return
self
.email
'''django自带后台权限控制,对哪些表有查看权限等'''
def
has_perm(
self
, perm, obj
=
None
):
"Does the user have a specific permission?"
# Simplest possible answer: Yes, always
return
True
'''用户是否有权限看到app'''
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
|
asset\models.py
1
|
from
asset.user_models
import
UserProfile
|
myCMDB\settings.py
1
|
AUTH_USER_MODEL
=
'asset.UserProfile'
|
asset\admin.py
1
2
|
from
asset
import
models
admin.site.register(models.UserProfile)
|
初始化数据库,登录后台。此时密码是明文显示,如果想改密码怎么办?
这时,需要自定义admin显示(官方都提供了)。
asset\admin.py
1
2
|
from
user_admin
import
UserAdmin
admin.site.register(models.UserProfile,UserAdmin)
|
asset\user_admin.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
|
#!/usr/bin/env python
# -*- coding:utf-8 -*-
from
django
import
forms
from
django.contrib
import
admin
from
django.contrib.auth.models
import
Group
from
django.contrib.auth.admin
import
UserAdmin as BaseUserAdmin
from
django.contrib.auth.forms
import
ReadOnlyPasswordHashField
from
asset.models
import
UserProfile
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
=
UserProfile
fields
=
(
'email'
,
'name'
)
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
=
UserProfile
fields
=
(
'email'
,
'password'
,
'name'
,
'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
UserAdmin(BaseUserAdmin):
# 以前是ModelAdmin
# 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'
,
'name'
,
'is_admin'
)
#这个和以前一样,显示什么
list_filter
=
(
'is_admin'
,)
fieldsets
=
(
(
None
, {
'fields'
: (
'email'
,
'password'
)}),
(
'Personal info'
, {
'fields'
: (
'name'
,)}),
(
'Permissions'
, {
'fields'
: (
'is_admin'
,)}),
)
# add_fieldsets is not a standard ModelAdmin attribute. UserAdmin
# overrides get_fieldsets to use this attribute when creating a user.
add_fieldsets
=
(
(
None
, {
'classes'
: (
'wide'
,),
'fields'
: (
'email'
,
'name'
,
'password1'
,
'password2'
)}
),
)
search_fields
=
(
'email'
,)
ordering
=
(
'email'
,)
filter_horizontal
=
()
# Now register the new UserAdmin...
#admin.site.register(UserProfile, UserAdmin)
# ... and, since we're not using Django's built-in permissions,
# unregister the Group model from admin.
admin.site.unregister(Group)
#不显示系统自带的group
|
后台效果