from:http://my.oschina.net/duoduo3369/blog/212842
目录[-]
django使用自己的用户系统
用过django的人应该都会知道admin,什么,真的没用过?汗,如果这样的话先看看这个
https://docs.djangoproject.com/en/1.6/ref/contrib/admin/
django自带用户系统,通过上面的admin,以及auth可以方便的管理用户。
不过,需求是多变的,比如,你有一个变态的用户系统,用户可能有大中小三张头像,
除了fisrt name ,last name外还有middle name,T^T name巴拉巴拉,django
的用户系统可能满足不了你的需求,这时候需要用自己的用户系统了,如何能在满足
需求的时候充分又利用到django的用户系统?
官方文档如下,内有详细说明,有英文厌烦症的可以直接略过
https://docs.djangoproject.com/en/dev/topics/auth/customizing/
其实步骤很简单
- 写自己的auth模块(定义user class);
- admin.py 注册到django的admin后台,并且修改一些field
- 修改settings.py中相应配置
step-1 写自己的auth模块(定义user class)
新建一个模块,名字随意,假设叫做myauth
User class继承AbstractBaseUser,UserManager继承BaseUserManager
重写对应的方法,建议浏览下AbstractBaseUser, BaseUserManager的源码
User类不用说,也就是根据自己业务定义的用户class,Manager就是django中
的Manager,做的事情你肯定经常用到,obj.objects.filter(),其中的objects
就是Manager,文档如下
https://docs.djangoproject.com/en/dev/topics/db/managers/
code
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
|
# -*- coding: utf-
8
-*-
from django.db
import
models
from django.contrib.auth.models
import
(BaseUserManager, AbstractBaseUser)
class
UserManager(BaseUserManager):
def create_user(self, name, email, password=None):
if
not email:
raise ValueError(
'Users must have an email address'
)
user = self.model(
name=name,
email=UserManager.normalize_email(email),
)
user.set_password(password)
user.save(using=self._db)
return
user
def create_superuser(self, name, email, password=None):
user = self.create_user(name, email, password)
user.is_admin = True
user.save(using=self._db)
return
user
class
User(AbstractBaseUser):
''
'用户表'
''
name = models.CharField(max_length=
100
, unique=True)
email = models.EmailField(max_length=
100
, unique=True)
avatar = models.URLField(blank=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
is_delete = models.BooleanField(
default
=False)
is_active = models.BooleanField(
default
=True)
is_admin = models.BooleanField(
default
=False)
access_token = models.CharField(max_length=
100
, blank=True)
refresh_token = models.CharField(max_length=
100
, blank=True)
expires_in = models.BigIntegerField(max_length=
100
,
default
=
0
)
objects = UserManager()
USERNAME_FIELD =
'name'
REQUIRED_FIELDS = (
'email'
,)
class
Meta:
ordering = (
'-created_at'
,)
def __unicode__(self):
return
self.name
def get_full_name(self):
return
self.email
def get_short_name(self):
return
self.name
def has_perm(self, perm, obj=None):
return
True
def has_module_perms(self, app_label):
return
True
@property
def is_staff(self):
return
self.is_admin
|
重写的字段看下源码就可以解释到了:
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
|
1
. AbstractBaseUser已经有password, last_login,所以密码这些就不用费心了
2
. 由于get_username用到了self.USERNAME_FIELD,所以需要指明哪个字段为用户名
3
. get_short_name,get_full_name需要实现,否则会抛异常
4
. 其他就按照自己的业务来写即可
5
. UserManager重写下两个create方法
class
AbstractBaseUser(models.Model):
password = models.CharField(_(
'password'
), max_length=
128
)
last_login = models.DateTimeField(_(
'last login'
),
default
=timezone.now)
is_active = True
REQUIRED_FIELDS = []
class
Meta:
abstract
= True
def get_username(self):
"Return the identifying username for this User"
return
getattr(self, self.USERNAME_FIELD)
def __str__(self):
return
self.get_username()
def natural_key(self):
return
(self.get_username(),)
def is_anonymous(self):
""
"
Always returns False. This is a way of comparing User objects to
anonymous users.
""
"
return
False
def is_authenticated(self):
""
"
Always
return
True. This is a way to tell
if
the user has been
authenticated in templates.
""
"
return
True
def set_password(self, raw_password):
self.password = make_password(raw_password)
def check_password(self, raw_password):
""
"
Returns a
boolean
of whether the raw_password was correct. Handles
hashing formats behind the scenes.
""
"
def setter(raw_password):
self.set_password(raw_password)
self.save(update_fields=[
"password"
])
return
check_password(raw_password, self.password, setter)
def set_unusable_password(self):
# Sets a value that will never be a valid hash
self.password = make_password(None)
def has_usable_password(self):
return
is_password_usable(self.password)
def get_full_name(self):
raise NotImplementedError()
def get_short_name(self):
raise NotImplementedError()
|
step-2 admin.py 注册到django的admin后台,并且修改一些field
admin注册user,参考文档 https://docs.djangoproject.com/en/dev/ref/contrib/admin/
代码如下,感觉没什么需要说明的。
myauth/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
91
92
93
|
#coding: utf-
8
from django
import
forms
from django.contrib
import
admin
from django.contrib.auth.models
import
Group as DjangoGroup
from django.contrib.auth.admin
import
UserAdmin
from django.contrib.auth.forms
import
ReadOnlyPasswordHashField
from myauth.models
import
User
# 新增用户表单
class
UserCreateForm(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 = User
fields = (
'name'
,
'email'
)
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
(UserCreateForm, 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 = User
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):
form = UserChangeForm
add_form = UserCreateForm
list_display = (
'name'
,
'created_at'
,
'email'
,
'is_delete'
,
'is_admin'
)
search_fields = (
'name'
,
'email'
)
list_filter = (
'is_admin'
,)
readonly_fields = (
'created_at'
,
'updated_at'
)
fieldsets = (
(None, {
'fields'
: (
'name'
,
'email'
,
'password'
,
'avatar'
,)}),
(
'Personal info'
, {
'fields'
: (
'created_at'
,
'updated_at'
)}),
(
'Open token info'
,
{
'fields'
: (
'access_token'
,
'refresh_token'
,
'expires_in'
)
}
),
(
'Permissions'
, {
'fields'
: (
'is_delete'
,
'is_admin'
,
'is_active'
)}),
(
'Important dates'
, {
'fields'
: (
'last_login'
,)}),
)
add_fieldsets = (
(
None,
{
'classes'
: (
'wide'
,),
'fields'
: (
'name'
,
'email'
,
'password1'
,
'password2'
),
}
),
)
ordering = (
'created_at'
,)
filter_horizontal = ()
admin.site.register(User, MyUserAdmin)
|
step-3 修改settings.py中相应配置
添加 AUTH_USER_MODEL = 'myauth.User'
install_app不要忘记加上myauth模块
grep django的源码可以看到,很多地方直接使用了配置AUTH_USER_MODEL
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
user = models.ForeignKey(settings.AUTH_USER_MODEL)
def get_user_model():
""
"
Returns the User model that is active in
this
project.
""
"
from django.db.models
import
get_model
try
:
app_label, model_name = settings.AUTH_USER_MODEL.split(
'.'
)
except ValueError:
raise ImproperlyConfigured(
"AUTH_USER_MODEL must be of the form 'app_label.model_name'"
)
user_model = get_model(app_label, model_name)
if
user_model is None:
raise ImproperlyConfigured(
"AUTH_USER_MODEL refers to model '%s' that has not been installed"
% settings.AUTH_USER_MODEL)
return
user_model
|
ps: django admin更改主题,django admin的主题实在是太朴素了
https://riccardo.forina.me/bootstrap-your-django-admin-in-3-minutes/