Django--自定義用戶認證


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,或加入用戶組等等。



官方說明

官方文檔:

https://docs.djangoproject.com/en/1.9/topics/auth/customizing/#django.contrib.auth.models.PermissionsMixin.has_perms


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:​




















免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM