西游之路——python全栈——自定义用户认证

目录

  一、创建用户表

  二、在admin中设置展示内容

  三、在settings文件中指定用于用户认证的数据库表类

  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     #BaseUserManager  用户管理基类,用于创建用户
 6     #AbstractBaseUser    抽象类,声明一些必须字段,不会自己生产表,继承的子类才会,主要内容:class Meta  abstract=True
 7     #PermissionMixin    权限管理类,也是抽象类
 8 )
 9 
10 class UserProFileManager(BaseUserManager):  #用于创建用户,需要在settings文件中声明
11     def create_user(self, email, name, password=None):
12         """
13         Creates and saves a User with the given email, name and password.
14         """
15         if not email:
16             raise ValueError('Users must have an email address')
17 
18         user = self.model(
19             email=self.normalize_email(email),
20             name=name,
21         )
22 
23         user.set_password(password)
24         user.save(using=self._db)
25         return user
26 
27     def create_superuser(self, email, name, password):
28         """
29         Creates and saves a superuser with the given email, name and password.
30         """
31         user = self.create_user(
32             email,
33             password=password,
34             name=name,
35         )
36         user.is_superuser = True
37         user.save(using=self._db)
38         return user
39 
40 class UserProFile(AbstractBaseUser,PermissionsMixin):
41     email = models.EmailField(
42         verbose_name='email address',
43         max_length=255,
44         unique=True,
45         blank=True,
46         null=True
47     )
48     password = models.CharField(
49         verbose_name='password',
50         max_length=128,
51         help_text=mark_safe("<a class='btn-link'href='password'>重置密码</a>"),
52     )
53     name = models.CharField(max_length=32, verbose_name='姓名')
54     #  null=True, null has no effect on ManyToManyField.,null对于manytomanyfield无作用,会报警
55     role = models.ManyToManyField('Role', null=True, blank=True)
56     is_active = models.BooleanField(default=True)
57     is_staff = models.BooleanField(default=True)
58     is_superuser = models.BooleanField(default=False)  #其中is_admin没有作用,is_superuser才是设置超级用户
59 
60     objects = UserProFileManager() #用户管理类和自定义用户表关联
61 
62     USERNAME_FIELD = 'email'
63     REQUIRED_FIELDS = ['name']
64 
65     def get_full_name(self):
66         # The user is identified by their email address
67         return self.email
68 
69     def get_short_name(self):
70         # The user is identified by their email address
71         return self.email
72 
73     def __str__(self):              # __unicode__ on Python 2
74         return self.email
75 
76     class Meta:
77         # verbose_name = 'CRM账户'
78         verbose_name_plural = 'CRM账户'
79         permissions = (  #用于管理权限条目
80             # ('自定义权限名','解释'),
81             ('crm_table_list', '可以查看kingadmin所有表的数据'),
82             ('crm_table_list_view', '可以查看kingadmin所有表里数据的修改页'),
83             ('crm_table_list_change', '可以修改kingadmin所有表数据'),
84             ('crm_table_list_add_view', '可以查看kingadmin所有表添加页'),
85             ('crm_table_list_add', '可以在kingadmin所有表添加数据'),
86             ('crm_personal_password_reset_view', '可以在kingadmin查看自己的秘密修改页'),
87             ('crm_personal_password_reset', '可以在kingadmin修改自己的密码'),
88         )
用户模型表
在基类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让数据表定义生效。



第二步: 在admin文件中设置展示内容

  1 from crm import models
  2 
  3 from django import forms
  4 from django.contrib import admin
  5 from django.contrib.auth.models import Group
  6 from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
  7 from django.contrib.auth.forms import ReadOnlyPasswordHashField
  8 
  9 from crm.models import UserProFile
 10 
 11 class UserCreationForm(forms.ModelForm):  #创建时显示的表单信息
 12     """A form for creating new users. Includes all the required
 13     fields, plus a repeated password."""
 14     password1 = forms.CharField(label='Password', widget=forms.PasswordInput)
 15     password2 = forms.CharField(label='Password confirmation', widget=forms.PasswordInput)
 16 
 17     class Meta:
 18         model = UserProFile
 19         fields = ('email', 'name')
 20 
 21     def clean_password2(self):  #对字段进行验证
 22         # Check that the two password entries match
 23         password1 = self.cleaned_data.get("password1")
 24         password2 = self.cleaned_data.get("password2")
 25         if password1 and password2 and password1 != password2:
 26             raise forms.ValidationError("Passwords don't match")
 27         return password2
 28 
 29     def save(self, commit=True):
 30         # Save the provided password in hashed format
 31         user = super().save(commit=False)
 32         user.set_password(self.cleaned_data["password1"])   # 把明文 根据算法改成密文
 33         if commit:
 34             user.save()
 35         return user
 36 
 37 class UserChangeForm(forms.ModelForm):   #修改时显示的表单信息
 38     """A form for updating users. Includes all the fields on
 39     the user, but replaces the password field with admin's
 40     password hash display field.
 41     """
 42     password = ReadOnlyPasswordHashField()  #密码字段显示时是hash加密只读字段
 43 
 44     class Meta:
 45         model = UserProFile
 46         fields = ('email', 'password', 'name', 'is_active', 'is_superuser')
 47 
 48     def clean_password(self):
 49         # Regardless of what the user provides, return the initial value.
 50         # This is done here, rather than on the field, because the
 51         # field does not have access to the initial value
 52         return self.initial["password"]
 53 
 54 class UserProFileAdmin(BaseUserAdmin):   #用于注册的表类
 55     # The forms to add and change user instances
 56     form = UserChangeForm
 57     add_form = UserCreationForm
 58 
 59     # The fields to be used in displaying the User model.
 60     # These override the definitions on the base UserAdmin
 61     # that reference specific fields on auth.User.
 62     list_display = ('email', 'name', 'is_superuser')
 63     list_filter = ('is_superuser',)
 64     fieldsets = (  #用于修改显示
 65         (None, {'fields': ('email', 'password')}),
 66         ('Personal info', {'fields': ('name',)}),
 67         ('Permissions', {'fields': ('is_active','is_staff','is_superuser','role','user_permissions','groups',)}),
 68     )
 69     # add_fieldsets is not a standard ModelAdmin attribute. UserAdmin
 70     # overrides get_fieldsets to use this attribute when creating a user.
 71     add_fieldsets = (   #用于添加,显示
 72         (None, {
 73             'classes': ('wide',),
 74             'fields': ('email', 'name', 'password1', 'password2')}
 75         ),
 76     )
 77     search_fields = ('email',)
 78     ordering = ('email',)
 79     filter_horizontal = ('role','groups','user_permissions')
 80 
 81 
 82 class CustomerAdmin(admin.ModelAdmin):
 83     list_display = ['name', 'source', 'contact_type', 'contact', 'consultant', 'consult_content', 'status', 'date']
 84     list_filter = ['source', 'consultant', 'status', 'date']
 85     search_fields = ['name','contact','source']
 86     # readonly_fields = ['contact','status']
 87     filter_horizontal = ['consult_courses']
 88     actions = ['change_status', ]
 89 
 90     def change_status(self, request, querysets):
 91         print(self, request, querysets)
 92         querysets.update(status=0)
 93 
 94 admin.site.register(models.CustomerInfo,CustomerAdmin)
 95 admin.site.register(models.Menus)
 96 admin.site.register(models.UserProFile,UserProFileAdmin)
 97 admin.site.register(models.StudyRecord)
 98 admin.site.register(models.CustomerFollowUp)
 99 admin.site.register(models.Course)
100 admin.site.register(models.ClassList)
101 admin.site.register(models.CourseRecord)
102 admin.site.register(models.Branch)
103 admin.site.register(models.StudentEnrollment)
104 admin.site.register(models.ContractTemplate)
admin中自定义的form与注册代码
UserCreationForm  # 创建新用户表单
UserChangeForm    # 改变用户信息表单

第三步:需要在settings.py中指定用于用户认证的数据库表类

1 #上面的值表示Django应用的名称(必须位于INSTALLLED_APPS中)和你想使用的User模型的名称。
2 AUTH_USER_MODEL = 'crm.UserProFile'  # 告知Django使用自定义验证

  最后,如果项目中已经存在其他的app,其他的app可能需要依赖UserProfile表,所以需要先将wolf注册,然后python manage.py makemigrations和python manage.py migrate同步之后,在将其他的app注册进来,创建其对应的表结构;

如果其他的表结果已经创建了,在运气非常不好的情况下,可能需要删除表才可以le~~~~~

原文地址:https://www.cnblogs.com/Lujun1028/p/9958025.html