自定义用户认证(三)

一、开发目标

1、引子

class UserProfile(models.Model):
    """堡垒机的账户"""
    user = models.OneToOneField(User)
    name = models.CharField(max_length=64)
    bind_hosts = models.ManyToManyField("BindHost",blank=True)
    host_groups = models.ManyToManyField(HostGroup)
     
    def __str__(self):
        return self.name

真正你在生产中不是这这么玩的,要完全自定制
自定制就是把class User(AbstractUser)这个表重写了,把他去掉之直接继承下面的

class AbstractUser(AbstractBaseUser, PermissionsMixin):

2、class AbstractUser表的的字段都在哪里 

AbstractBaseUser类代码

class AbstractUser(AbstractBaseUser, PermissionsMixin):
    """
    An abstract base class implementing a fully featured User model with
    admin-compliant permissions.

    Username, password and email are required. Other fields are optional.
    """
    username = models.CharField(_('username'), max_length=30, unique=True,
        help_text=_('Required. 30 characters or fewer. Letters, digits and '
                    '@/./+/-/_ only.'),
        validators=[
            validators.RegexValidator(r'^[\w.@+-]+$',
                                      _('Enter a valid username. '
                                        'This value may contain only letters, numbers '
                                        'and @/./+/-/_ characters.'), 'invalid'),
        ],
        error_messages={
            'unique': _("A user with that username already exists."),
        })
    first_name = models.CharField(_('first name'), max_length=30, blank=True)
    last_name = models.CharField(_('last name'), max_length=30, blank=True)
    email = models.EmailField(_('email address'), blank=True)
    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()

    USERNAME_FIELD = 'username'
    REQUIRED_FIELDS = ['email']

后台web截图

PermissionsMixin类代码

class PermissionsMixin(models.Model):
    """
    A mixin class that adds the fields and methods necessary to support
    Django's Group and Permission model using the ModelBackend.
    """
    is_superuser = models.BooleanField(_('superuser status'), default=False,
        help_text=_('Designates that this user has all permissions without '
                    'explicitly assigning them.'))
    groups = models.ManyToManyField(Group, verbose_name=_('groups'),
        blank=True, help_text=_('The groups this user belongs to. A user will '
                                'get all permissions granted to each of '
                                'their groups.'),
        related_name="user_set", related_query_name="user")
    user_permissions = models.ManyToManyField(Permission,
        verbose_name=_('user permissions'), blank=True,
        help_text=_('Specific permissions for this user.'),
        related_name="user_set", related_query_name="user")

    class Meta:
        abstract = True

截图

 二、官网自定义用户认证

1、自定义参考官方说明

https://docs.djangoproject.com/en/2.1/topics/auth/customizing/

登陆已经变成如下图了

Specifying a custom User model(指定自定义用户模型)

使用Django自定义用户模型必须满足:

  1. 模型必须有一个唯一的字段,可用于识别目的。

  2. 用户给定名称为“短”的标识,用户的全名为“长”标识符。他们可以返回完全相同的值。

     构建一个符合用户自定义模型的最简单的方法是继承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

后台效果

编辑用户:

更改密码:

没有Group:​

猜你喜欢

转载自www.cnblogs.com/luoahong/p/9458474.html