前言
Django附帶的認證對于大多數常見情況來說已經足夠了,但是如何在 Django 中使用自定義的數據表進行用戶認證,有一種較為笨蛋的辦法就是自定義好數據表后,使用OnetoOne來跟 Django 的表進行關聯,類似于這樣:
1
2
3
4
5
6
7
8
9
10
11
12
|
from django.contrib.auth.models import User class UserProfile(models.Model): """ 用戶賬號表 """ user = models.OneToOneField(User) name = models.CharField(max_length = 32 ) def __str__( self ): return self .name class Meta: verbose_name_plural = verbose_name = "用戶賬號" ordering = [ 'id' ] |
這樣做雖然可以簡單、快速的實現,但是有一個問題就是我們在自己的表中創建一個用戶就必須再跟 admin 中的一個用戶進行關聯,這簡直是不可以忍受的。
admin代替默認User model
寫我們自定義的 models 類來創建用戶數據表來代替默認的User model,而不與django 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
67
|
from django.db import models from django.contrib.auth.models import User from django.contrib.auth.models import ( BaseUserManager, AbstractBaseUser ) class UserProfileManager(BaseUserManager): def create_user( self , email, name, password = None ): """ 用戶創建,需要提供 email、name、password """ 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): """ 超級用戶創建,需要提供 email、name、password """ user = self .create_user( email, password = password, name = name, ) user.is_admin = True user.is_active = 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 , verbose_name = "用戶名稱" ) phone = models.IntegerField( "電話" ) is_active = models.BooleanField(default = True ) is_admin = models.BooleanField(default = False ) objects = UserProfileManager() USERNAME_FIELD = 'email' # 將email 作為登入用戶名 REQUIRED_FIELDS = [ 'name' , 'phone' ] def __str__( self ): return self .email 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 has_perm( self , perm, obj = None ): "Does the user have a specific permission?" # Simplest possible answer: Yes, always return True 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 |
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
|
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 = models.UserProfile fields = ( 'email' , 'name' ) def clean_password2( self ): 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 ): 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 = models.UserProfile fields = ( 'email' , 'password' , 'name' , 'is_active' , 'is_admin' ) def clean_password( self ): return self .initial[ "password" ] class UserProfileAdmin(BaseUserAdmin): form = UserChangeForm add_form = UserCreationForm list_display = ( 'email' , 'name' , 'is_admin' , 'is_staff' ) list_filter = ( 'is_admin' ,) fieldsets = ( ( None , { 'fields' : ( 'email' , 'password' )}), ( 'Personal info' , { 'fields' : ( 'name' ,)}), ( 'Permissions' , { 'fields' : ( 'is_admin' , 'is_active' , 'roles' , 'user_permissions' , 'groups' )}), ) add_fieldsets = ( ( None , { 'classes' : ( 'wide' ,), 'fields' : ( 'email' , 'name' , 'password1' , 'password2' )} ), ) search_fields = ( 'email' ,) ordering = ( 'email' ,) filter_horizontal = ( 'groups' , 'user_permissions' , 'roles' ) |
2.Django允許您通過AUTH_USER_MODEL配置來引用自定義的model設置來覆蓋默認User模型,這個配置的配置方法為在 settings 中加入:AUTH_USER_MODEL = "APP.model_class"
,例如本例中我們需要在 setting 中加入以下配置:
1
|
AUTH_USER_MODEL = "app1.UserProfile" |
3.部署
1
2
|
python manage.py makemigrations python manage.py migrate |
創建一個新用戶,此時我們就可以用這個用戶來登錄 admin 后臺了
1
|
python manage.py createsuperuser |
效果如下:
自定義認證
那如果我們需要使用我們自己的認證系統呢,假如我們有一個 login 頁面和一個 home 頁面:
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
|
from django.shortcuts import render, HttpResponse, redirect from django.contrib.auth import authenticate,login,logout from app1 import models from django.contrib.auth.decorators import login_required def auth_required(auth_type): # 認證裝飾器 def wapper(func): def inner(request, * args, * * kwargs): if auth_type = = 'admin' : ck = request.COOKIES.get( "login" ) # 獲取當前登錄的用戶 if request.user.is_authenticated() and ck: return func(request, * args, * * kwargs) else : return redirect( "/app1/login/" ) return inner return wapper def login_auth(request): # 認證 if request.method = = "GET" : return render(request, 'login.html' ) elif request.method = = "POST" : username = request.POST.get( 'username' , None ) password = request.POST.get( 'password' , None ) user = authenticate(username = username, password = password) if user is not None : if user.is_active: login(request, user) _next = request.GET.get( "next" , '/crm' ) return redirect( '_next' ) else : return redirect( '/app1/login/' ) else : return redirect( '/app1/login/' ) else : pass def my_logout(request): # 注銷 if request.method = = 'GET' : logout(request) return redirect( '/app1/login/' ) @login_required def home(request): # home page path1, path2 = "Home" , '主頁' if request.method = = "GET" : return render(request, 'home.html' , locals ()) elif request.method = = "POST" : pass |
總結
以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對服務器之家的支持。
原文鏈接:http://www.cnblogs.com/forsaken627/p/8523371.html