西游之路——python全栈——自定义用户认证
Posted 陆游憩
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了西游之路——python全栈——自定义用户认证相关的知识,希望对你有一定的参考价值。
django自定义用户认证(使用自定义的UserProfile,而不是django自带的),就需要(django要求)将为UserProfile单独创建一个app,这个app啥也不干,就是为UserProfile而生的;
这里我们创建一个app,名字叫做custom_auth,事实上,我们只需要对其中的models文件和admin.py做操作就可以了;
第一步:
创建user model
下面是models.py文件的内容:
1 from django.utils.safestring import mark_safe
2 from django.db import models
3 from django.contrib.auth.models import (
4 BaseUserManager, AbstractBaseUser,PermissionsMixin
5 )
6
7 class UserProFileManager(BaseUserManager):
8 def create_user(self, email, name, password=None):
9 """
10 Creates and saves a User with the given email, name and password.
11 """
12 if not email:
13 raise ValueError(‘Users must have an email address‘)
14
15 user = self.model(
16 email=self.normalize_email(email),
17 name=name,
18 )
19
20 user.set_password(password)
21 user.save(using=self._db)
22 return user
23
24 def create_superuser(self, email, name, password):
25 """
26 Creates and saves a superuser with the given email, name and password.
27 """
28 user = self.create_user(
29 email,
30 password=password,
31 name=name,
32 )
33 user.is_superuser = True
34 user.save(using=self._db)
35 return user
36
37 class UserProFile(AbstractBaseUser,PermissionsMixin):
38 email = models.EmailField(
39 verbose_name=‘email address‘,
40 max_length=255,
41 unique=True,
42 blank=True,
43 null=True
44 )
45 password = models.CharField(
46 verbose_name=‘password‘,
47 max_length=128,
48 help_text=mark_safe("<a class=‘btn-link‘href=‘password‘>重置密码</a>"),
49 )
50 name = models.CharField(max_length=32, verbose_name=‘姓名‘)
51 role = models.ManyToManyField(‘Role‘, null=True, blank=True)
52 is_active = models.BooleanField(default=True)
53 is_staff = models.BooleanField(default=True)
54 is_superuser = models.BooleanField(default=False)
55
56 objects = UserProFileManager()
57
58 USERNAME_FIELD = ‘email‘
59 REQUIRED_FIELDS = [‘name‘]
60
61 def get_full_name(self):
62 # The user is identified by their email address
63 return self.email
64
65 def get_short_name(self):
66 # The user is identified by their email address
67 return self.email
68
69 def __str__(self): # __unicode__ on Python 2
70 return self.email
71
72 class Meta:
73 # verbose_name = ‘CRM账户‘
74 verbose_name_plural = ‘CRM账户‘
75 permissions = (
76 (‘crm_table_list‘, ‘可以查看kingadmin所有表的数据‘),
77 (‘crm_table_list_view‘, ‘可以查看kingadmin所有表里数据的修改页‘),
78 (‘crm_table_list_change‘, ‘可以修改kingadmin所有表数据‘),
79 (‘crm_table_list_add_view‘, ‘可以查看kingadmin所有表添加页‘),
80 (‘crm_table_list_add‘, ‘可以在kingadmin所有表添加数据‘),
81 (‘crm_personal_password_reset_view‘, ‘可以在kingadmin查看自己的秘密修改页‘),
82 (‘crm_personal_password_reset‘, ‘可以在kingadmin修改自己的密码‘),
83 )
在基类AbstractBaseUser中:
class Meta:
abstract = True 只把传递给继承者,自身不创建表
对于类UaerproFile注意如下:
其中objects = UserProfileManager()是为了引用创建超级用户和普通用户所定义的方法,USERNAME_FIELD,REQUIRED_FIELDS按需进行修改;
USERNAME_FIELD = ‘email‘ # 定义哪个字段是用户名字段,即对应登陆页面中的用户名
REQUIRED_FIELDS = [‘name‘] # 定义必填字段有哪些
即python3.6 manage.py createsuperuser调用的方法,这个类就定义了两个方法,create_user和create_superuser:
对于类UserProfileManager注意如下:
这里需要注意的是,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让数据表定义生效。
第二步:
to register this custom user model with Django’s admin, the following code would be required in the app’s admin.py
file
1 from crm import models
2
3
4
5 from django import forms
6 from django.contrib import admin
7 from django.contrib.auth.models import Group
8 from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
9 from django.contrib.auth.forms import ReadOnlyPasswordHashField
10
11 from crm.models import UserProFile
12
13
14 class UserCreationForm(forms.ModelForm):
15 """A form for creating new users. Includes all the required
16 fields, plus a repeated password."""
17 password1 = forms.CharField(label=‘Password‘, widget=forms.PasswordInput)
18 password2 = forms.CharField(label=‘Password confirmation‘, widget=forms.PasswordInput)
19
20 class Meta:
21 model = UserProFile
22 fields = (‘email‘, ‘name‘)
23
24 def clean_password2(self):
25 # Check that the two password entries match
26 password1 = self.cleaned_data.get("password1")
27 password2 = self.cleaned_data.get("password2")
28 if password1 and password2 and password1 != password2:
29 raise forms.ValidationError("Passwords don‘t match")
30 return password2
31
32 def save(self, commit=True):
33 # Save the provided password in hashed format
34 user = super().save(commit=False)
35 user.set_password(self.cleaned_data["password1"]) # 把明文 根据算法改成密文
36 if commit:
37 user.save()
38 return user
39
40 class UserChangeForm(forms.ModelForm):
41 """A form for updating users. Includes all the fields on
42 the user, but replaces the password field with admin‘s
43 password hash display field.
44 """
45 password = ReadOnlyPasswordHashField()
46
47 class Meta:
48 model = UserProFile
49 fields = (‘email‘, ‘password‘, ‘name‘, ‘is_active‘, ‘is_superuser‘)
50
51 def clean_password(self):
52 # Regardless of what the user provides, return the initial value.
53 # This is done here, rather than on the field, because the
54 # field does not have access to the initial value
55 return self.initial["password"]
56
57 class UserProFileAdmin(BaseUserAdmin):
58 # The forms to add and change user instances
59 form = UserChangeForm
60 add_form = UserCreationForm
61
62 # The fields to be used in displaying the User model.
63 # These override the definitions on the base UserAdmin
64 # that reference specific fields on auth.User.
65 list_display = (‘email‘, ‘name‘, ‘is_superuser‘)
66 list_filter = (‘is_superuser‘,)
67 fieldsets = (
68 (None, {‘fields‘: (‘email‘, ‘password‘)}),
69 (‘Personal info‘, {‘fields‘: (‘name‘,)}),
70 (‘Permissions‘, {‘fields‘: (‘is_active‘,‘is_staff‘,‘is_superuser‘,‘role‘,‘user_permissions‘,‘groups‘,)}),
71 )
72 # add_fieldsets is not a standard ModelAdmin attribute. UserAdmin
73 # overrides get_fieldsets to use this attribute when creating a user.
74 add_fieldsets = (
75 (None, {
76 ‘classes‘: (‘wide‘,),
77 ‘fields‘: (‘email‘, ‘name‘, ‘password1‘, ‘password2‘)}
78 ),
79 )
80 search_fields = (‘email‘,)
81 ordering = (‘email‘,)
82 filter_horizontal = (‘role‘,‘groups‘,‘user_permissions‘)
83
84
85
86
87
88 class CustomerAdmin(admin.ModelAdmin):
89 list_display = [‘name‘, ‘source‘, ‘contact_type‘, ‘contact‘, ‘consultant‘, ‘consult_content‘, ‘status‘, ‘date‘]
90 list_filter = [‘source‘, ‘consultant‘, ‘status‘, ‘date‘]
91 search_fields = [‘name‘,‘contact‘,‘source‘]
92 # readonly_fields = [‘contact‘,‘status‘]
93 filter_horizontal = [‘consult_courses‘]
94 actions = [‘change_status‘, ]
95
96 def change_status(self, request, querysets):
97 print(self, request, querysets)
98 querysets.update(status=0)
99
100 admin.site.register(models.CustomerInfo,CustomerAdmin)
101 admin.site.register(models.Menus)
102 admin.site.register(models.UserProFile,UserProFileAdmin)
103 admin.site.register(models.StudyRecord)
104 admin.site.register(models.CustomerFollowUp)
105 admin.site.register(models.Course)
106 admin.site.register(models.ClassList)
107 admin.site.register(models.CourseRecord)
108 admin.site.register(models.Branch)
109 admin.site.register(models.StudentEnrollment)
110 admin.site.register(models.ContractTemplate)
UserCreationForm # 创建新用户表单
UserChangeForm # 改变用户信息表单
第三步:
需要在settings.py中指定用于用户认证的数据库表类
1 AUTH_USER_MODEL = ‘Wolf.UserProfile‘ #AppName.自定义user
最后,如果项目中已经存在其他的app,其他的app可能需要依赖UserProfile表,所以需要先将wolf注册,然后python manage.py makemigrations和python manage.py migrate同步之后,在将其他的app注册进来,创建其对应的表结构;
如果其他的表结果已经创建了,在运气非常不好的情况下,可能需要删除表才可以le~~~~~
以上是关于西游之路——python全栈——自定义用户认证的主要内容,如果未能解决你的问题,请参考以下文章