自定義Django使用者模型
阿新 • • 發佈:2019-02-03
Django最方便的一點可以說就是自帶的使用者系統了,不過某些情況下自帶的使用者系統不太符合專案需求,比如你想新增幾個欄位怎麼辦?當然可以使用自定Model然後外來鍵關聯User類來實現,不過一方面關聯查詢的效率比直接查詢效率要低,另一方面想刪除系統自帶使用者系統的某些欄位怎麼辦呢?
所以,自定義使用者模型可以說是一種很常見的需求。這裡以Django1.9為例,記錄一下自定義使用者模型的方法。
首先新建一個APP,我這裡叫做’accounts’,為了簡單起見,我只定義一個包含使用者名稱、密碼、手機號、是否有效、是否是管理員的類。編寫models.py檔案:
1 2 3 4 5 6 7 8 9 10 11 | # coding=utf-8 from __future__ import unicode_literals from django.db import models from django.contrib.auth.models import |
由於不想要自帶的某些欄位,比如email、firstname一類的,所以繼承了AbstractBaseUser,這個類只提供了password、last_login這幾個基本屬性。USERNAME_FIELD定義了登入的使用者名稱是哪個,REQUIRED_FIELDS則定義了哪些是必填欄位,後面的3個方法都和許可權相關,為了簡單這裡都返回True,實際情況需要根據需求進行修改。
接下來修改admin.py,否則在管理介面是看不到自定義使用者模型的:
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 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 | from django import forms from django.contrib import admin from django.contrib.auth.models import Group from django.contrib.auth.admin import UserAdmin as BaseUserAdmin from django.contrib.auth.forms import ReadOnlyPasswordHashField from accounts.models import MyUser 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 = MyUser fields = ('username','phone') def clean_password2(self): # Check that the two password entries match 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): # Save the provided password in hashed format 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 = MyUser fields = ('username', 'password','phone', 'is_active', 'is_admin') def clean_password(self): # Regardless of what the user provides, return the initial value. # This is done here, rather than on the field, because the # field does not have access to the initial value return self.initial["password"] class UserAdmin(BaseUserAdmin): # The forms to add and change user instances form = UserChangeForm add_form = UserCreationForm # The fields to be used in displaying the User model. # These override the definitions on the base UserAdmin # that reference specific fields on auth.User. list_display = ('username','jy_partner', 'is_admin') list_filter = ('is_admin',) fieldsets = ( (None, {'fields': ('username', 'password')}), ('Personal info', {'fields': ('phone',)}), ('Permissions', {'fields': ('is_admin',)}), ) # add_fieldsets is not a standard ModelAdmin attribute. UserAdmin # overrides get_fieldsets to use this attribute when creating a user. add_fieldsets = ( (None, { 'classes': ('wide',), 'fields': ('username', 'phone', 'password1', 'password2')} ), ) search_fields = ('username',) ordering = ('username',) filter_horizontal = () # Now register the new UserAdmin... admin.site.register(MyUser, UserAdmin) # ... and, since we're not using Django's built-in permissions, # unregister the Group model from admin. admin.site.unregister(Group) |
這裡我們定義了2個Form用於建立、修改使用者時使用,然後把我們自定義的使用者模型註冊到管理頁面中,由於我們使用自定義使用者模型所以無法使用Django自帶的許可權系統,注意最後一句把組功能在管理後臺移除。
關於許可權部分可以看官網文件。
如此自定義模型後,登入時需要手動指定後端,否則會報錯:AttributeError: 'MyUser' object has no attribute 'backend'