自定义的用户认证在django的官方网站中有详细的说明:
https://docs.djangoproject.com/en/2.0/topics/auth/customizing/
第一步:首先需要在models.py中需要定义两部分
1. 用于认证的数据表字段信息:
1 class UserProfile(AbstractBaseUser): 2 email = models.EmailField( 3 verbose_name='邮箱地址', 4 max_length=255, 5 unique=True, 6 ) 7 name = models.CharField(max_length=32, verbose_name='用户名称') 8 date_of_birth = models.DateField(null=True, verbose_name='出生日期') 9 is_active = models.BooleanField(default=True) 10 is_admin = models.BooleanField(default=False) 11 12 objects = UserProfileManager() 13 14 USERNAME_FIELD = 'email' # 定义哪个字段是用户名字段,即对应登陆页面中的用户名 15 # REQUIRED_FIELDS = ['date_of_birth'] 16 REQUIRED_FIELDS = ['name'] # 定义必填字段有哪些 17 18 def __str__(self): 19 return self.email 20 21 def has_perm(self, perm, obj=None): 22 "Does the user have a specific permission?" 23 # Simplest possible answer: Yes, always 24 return True 25 26 def has_module_perms(self, app_label): 27 "Does the user have permissions to view the app `app_label`?" 28 # Simplest possible answer: Yes, always 29 return True 30 31 @property 32 def is_staff(self): 33 "Is the user a member of staff?" 34 # Simplest possible answer: All admins are staff 35 return self.is_admin 36 37 def get_short_name(self): 38 """ 39 40 :return: 41 """ 42 pass 43 44 class Meta: 45 verbose_name = verbose_name_plural = '登陆账户'
其中objects = UserProfileManager()是为了引用创建超级用户和普通用户所定义的方法,USERNAME_FIELD,REQUIRED_FIELDS按需进行修改;
USERNAME_FIELD = 'email' # 定义哪个字段是用户名字段,即对应登陆页面中的用户名
REQUIRED_FIELDS = ['name'] # 定义必填字段有哪些
即python3.6 manage.py createsuperuser调用的方法,这个类就定义了两个方法,create_user和create_superuser:
1 class UserProfileManager(BaseUserManager): 2 def create_user(self, email, name, password=None): 3 """ 4 Creates and saves a User with the given email, date of 5 birth and password. 6 """ 7 if not email: 8 raise ValueError('Users must have an email address') 9 10 user = self.model( 11 email=self.normalize_email(email), 12 name=name, 13 # date_of_birth=date_of_birth, 14 ) 15 16 user.set_password(password) 17 user.is_active = True 18 user.save(using=self._db) 19 return user 20 21 def create_superuser(self, email, name, password): 22 """ 23 Creates and saves a superuser with the given email, date of 24 birth and password. 25 """ 26 user = self.create_user( 27 email, 28 password=password, 29 # date_of_birth=date_of_birth, 30 name=name, 31 ) 32 user.is_active = True 33 user.is_admin = True 34 user.save(using=self._db) 35 return user
这里需要注意的是,create_user/create_superuser需要与数据库对应的表定义的字段对应,参数传递也要一一对应;
用于认证的数据表需要定义一个get_short_name方法,否则会引发一个方法未重载的错误;原因就是UserProfile继承的基类
AbstractBaseUser强制重载该方法,如果没有该方法就引发一个异常:
def get_short_name(self):
raise NotImplementedError('subclasses of AbstractBaseUser must provide a get_short_name() method.')
数据表定义完后,需要python3.6 manage.py makemigrations/python3.6 manage.py migrate让数据表定义生效。
第二步:需要在admin.py中注册这两个类:UserProfile、UserProfileManager。
1 from django.contrib import admin 2 from django.shortcuts import render 3 from . import models 4 from django import forms 5 from django.contrib import admin 6 # from django.contrib.auth.models import Group 7 from django.contrib.auth.admin import UserAdmin as BaseUserAdmin 8 from django.contrib.auth.forms import ReadOnlyPasswordHashField 9 10 from CRM.models import UserProfile 11 12 # Register your models here. 13 14 15 class CustomerInfoAdmin(admin.ModelAdmin): 16 list_display = ('qq', 'name', 'consultant', 'consult_course', 'status', 'date') 17 list_filter = ('refer_path', 'consultant', 'date') 18 search_fields = ('qq', 'name') 19 raw_id_fields = ('consult_course', ) 20 list_editable = ('status', ) 21 filter_horizontal = ('tags', ) 22 actions = ("test_action",) 23 24 def test_action(self, request, arg2): 25 print('test action:', self, request, arg2) 26 return render(request, "kingadmin/default.html") 27 test_action.short_description = '测试' 28 29 30 class UserCreationForm(forms.ModelForm): 31 """A form for creating new users. Includes all the required 32 fields, plus a repeated password.""" 33 password1 = forms.CharField(label='Password', widget=forms.PasswordInput) 34 password2 = forms.CharField(label='Password confirmation', widget=forms.PasswordInput) 35 36 class Meta: 37 model = UserProfile 38 fields = ('email', 'name', 'date_of_birth') 39 40 def clean_password2(self): 41 # Check that the two password entries match 42 password1 = self.cleaned_data.get("password1") 43 password2 = self.cleaned_data.get("password2") 44 if password1 and password2 and password1 != password2: 45 raise forms.ValidationError("Passwords don't match") 46 return password2 47 48 def save(self, commit=True): 49 # Save the provided password in hashed format 50 user = super().save(commit=False) 51 user.set_password(self.cleaned_data["password1"]) 52 if commit: 53 user.save() 54 return user 55 56 57 class UserChangeForm(forms.ModelForm): 58 """A form for updating users. Includes all the fields on 59 the user, but replaces the password field with admin's 60 password hash display field. 61 """ 62 password = ReadOnlyPasswordHashField() 63 64 class Meta: 65 model = UserProfile 66 fields = ('email', 'password', 'name', 'date_of_birth', 'is_active', 'is_admin') 67 68 def clean_password(self): 69 # Regardless of what the user provides, return the initial value. 70 # This is done here, rather than on the field, because the 71 # field does not have access to the initial value 72 return self.initial["password"] 73 74 75 class UserProfileAdmin(BaseUserAdmin): 76 # The forms to add and change user instances 77 form = UserChangeForm 78 add_form = UserCreationForm 79 80 # The fields to be used in displaying the User model. 81 # These override the definitions on the base UserAdmin 82 # that reference specific fields on auth.User. 83 list_display = ('email', 'name', 'date_of_birth', 'is_admin') 84 list_filter = ('is_admin',) 85 fieldsets = ( 86 (None, {'fields': ('email', 'name', 'password')}), 87 ('Personal info', {'fields': ('date_of_birth',)}), 88 ('Permissions', {'fields': ('is_admin',)}), 89 ) 90 # add_fieldsets is not a standard ModelAdmin attribute. UserAdmin 91 # overrides get_fieldsets to use this attribute when creating a user. 92 add_fieldsets = ( 93 (None, { 94 'classes': ('wide',), 95 'fields': ('email', 'name', 'date_of_birth', 'password1', 'password2')} 96 ), 97 ) 98 search_fields = ('email',) 99 ordering = ('email',) 100 filter_horizontal = () 101 102 # Now register the new UserAdmin... 103 admin.site.register(UserProfile, UserProfileAdmin) 104 admin.site.register(models.CustomerInfo, CustomerInfoAdmin) 105 admin.site.register(models.Campus) 106 admin.site.register(models.ClassRecord) 107 admin.site.register(models.ClassTable) 108 admin.site.register(models.Curriculum) 109 admin.site.register(models.CustomerFollowUp) 110 admin.site.register(models.Enrollment) 111 admin.site.register(models.LearningRecord) 112 admin.site.register(models.Menu) 113 admin.site.register(models.PaymentRecord) 114 admin.site.register(models.Role) 115 admin.site.register(models.Tag) 116 # admin.site.register(models.UserProfile) 117 # admin.site.register(models.UserProfileManager) 118 admin.site.register(models.SubMenu)
UserCreationForm # 创建新用户表单
UserChangeForm # 改变用户信息表单
第三步:需要在settings.py中指定用于用户认证的数据库表类:
AUTH_USER_MODEL = 'CRM.UserProfile'
效果如下:
自此,用户自定义认证基本完成,但是目前只能了解到这个程度,以后了解更多会在这里补充,也欢迎高人指点!!!