前言
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