Django使用自己的用户系统,自定义用户系统

from:http://my.oschina.net/duoduo3369/blog/212842


摘要  用过django的人应该都会知道admin,不过,需求是多变的,比如,你有一个变态的用户系统,用户可能有大中小三张头像, 除了fisrt name ,last name外还有middle name,T^T name巴拉巴拉,django 的用户系统可能满足不了你的需求,这时候需要用自己的用户系统了,如何能在满足 需求的时候充分又利用到django的用户系统?

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/

其实步骤很简单

  1. 写自己的auth模块(定义user class);
  2. admin.py 注册到django的admin后台,并且修改一些field
  3. 修改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/

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值