1. 程式人生 > >西遊之路——python全棧——自定義用戶認證

西遊之路——python全棧——自定義用戶認證

widget conf import all pri code acc 情況下 mod

  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 )
models表結構

在基類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)
admin中自定義的form與註冊代碼

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全棧——自定義用戶認證