參考上篇博文,咱們利用了OneToOneField的方式使用了django自帶的user,http://www.cnblogs.com/caseast/p/5909248.html , 但這麼用有個問題,就是每次增刪改查數據,由於有外鍵的存在都要查詢兩次(固然能夠用select_related方式減小查詢次數,參考: Django models對象的select_related方法(減小查詢次數) ),另外在admin中須要維護2張表,先建立User,再在UserProfile中進行關聯操做。本篇就來介紹一下,如何定製User和admin達到如下目的:1.擴展django自帶的User,且不經過OneToOne的方式。2.修改User中的字段,讓諸如email這種字段變爲必選項(默認爲可選)。3.admin表單定製,讓不一樣權限的用戶顯示不一樣的頁面。
期間踩了不少坑,統一作一次整理,admin可定製的地方不少,可是定製的方法確定不如本身寫的後臺那麼靈活,須要大致瞭解django的User和admin的工做模式和源碼,怎麼取捨還看本身的需求了。html
擴展User的方法大概有4種,參考這個國外博客:https://simpleisbetterthancomplex.com/tutorial/2016/07/22/how-to-extend-django-user-model.html#proxy ,我用的是裏邊描述的第四種方法。
models.pypython
from django.db import models from django.contrib.auth.models import AbstractUser, Group # Create your models here. ''' OneToOne的擴展寫法,原來的寫法 class UserProfile(models.Model): user = models.OneToOneField(User) name = models.CharField(u'姓名', max_length=32, blank=False, null=False) class Meta: verbose_name = u'用戶詳情' verbose_name_plural = u"用戶詳情" ''' class MyUser(AbstractUser): # 繼承AbstractUser類,實際上django的User也是繼承他,咱們要作的就是用本身的類代替django本身的User name = models.CharField(u'中文名', max_length=32, blank=False, null=False) class Meta: verbose_name = u'用戶詳情' verbose_name_plural = u"用戶詳情"
這裏附上Django User類部分源碼web
class User(AbstractUser): """ Users within the Django authentication system are represented by this model. Username, password and email are required. Other fields are optional. """ class Meta(AbstractUser.Meta): swappable = 'AUTH_USER_MODEL'
光作以上這些還不夠,咱們須要告訴django,咱們不用你的User了,要用本身的,因此須要在settings.py裏從新設定一個變量
settings.pydjango
AUTH_USER_MODEL = "web_sso.MyUser" # 咱們的app叫web_sso,這個MyUser就是models定義的那個類
看下擴展完的效果,能夠看到,咱們不用再像以前同樣維護「用戶」和「用戶詳情」兩張表了,但仍是有不少小問題須要解決。
app
長話短說,直接看一下,個人admin.py改了哪些東西吧.
admin.pyide
from django.contrib import admin from web_sso import models from django.contrib.auth.admin import UserAdmin # 從django繼承過來後進行定製 from django.utils.translation import ugettext_lazy as _ from django.contrib.auth.forms import UserCreationForm, UserChangeForm # admin中涉及到的兩個表單 class User_exAdmin(admin.ModelAdmin): # 驗證碼部分展現 list_display = ('valid_code', 'valid_time', 'email') # custom user admin class MyUserCreationForm(UserCreationForm): # 增長用戶表單從新定義,繼承自UserCreationForm def __init__(self, *args, **kwargs): super(MyUserCreationForm, self).__init__(*args, **kwargs) self.fields['email'].required = True # 爲了讓此字段在admin中爲必選項,自定義一個form self.fields['name'].required = True # 其實這個name字段能夠不用設定required,由於在models中的MyUser類中已經設定了blank=False,但email字段在系統自帶User的models中已經設定爲 # email = models.EmailField(_('email address'), blank=True),除非直接改源碼的django(不建議這麼作),否則仍是自定義一個表單作一下繼承吧。 class MyUserChangeForm(UserChangeForm): # 編輯用戶表單從新定義,繼承自UserChangeForm def __init__(self, *args, **kwargs): super(MyUserChangeForm, self).__init__(*args, **kwargs) self.fields['email'].required = True self.fields['name'].required = True class CustomUserAdmin(UserAdmin): def __init__(self, *args, **kwargs): super(CustomUserAdmin, self).__init__(*args, **kwargs) self.list_display = ('username', 'name', 'email', 'is_active', 'is_staff', 'is_superuser') self.search_fields = ('username', 'email', 'name') self.form = MyUserChangeForm # 編輯用戶表單,使用自定義的表單 self.add_form = MyUserCreationForm # 添加用戶表單,使用自定義的表單 # 以上的屬性均可以在django源碼的UserAdmin類中找到,咱們作以覆蓋 def changelist_view(self, request, extra_context=None): # 這個方法在源碼的admin/options.py文件的ModelAdmin這個類中定義,咱們要從新定義它,以達到不一樣權限的用戶,返回的表單內容不一樣 if not request.user.is_superuser: # 非super用戶不能設定編輯是否爲super用戶 self.fieldsets = ((None, {'fields': ('username', 'password',)}), (_('Personal info'), {'fields': ('name', 'email')}), # _ 將('')裏的內容國際化,這樣可讓admin裏的文字自動隨着LANGUAGE_CODE切換中英文 (_('Permissions'), {'fields': ('is_active', 'is_staff', 'groups')}), (_('Important dates'), {'fields': ('last_login', 'date_joined')}), ) # 這裏('Permissions')中沒有'is_superuser',此字段定義UserChangeForm表單中的具體顯示內容,並能夠分類顯示 self.add_fieldsets = ((None, {'classes': ('wide',), 'fields': ('username', 'name', 'password1', 'password2', 'email', 'is_active', 'is_staff', 'groups'), }), ) #此字段定義UserCreationForm表單中的具體顯示內容 else: # super帳戶能夠作任何事 self.fieldsets = ((None, {'fields': ('username', 'password',)}), (_('Personal info'), {'fields': ('name', 'email')}), (_('Permissions'), {'fields': ('is_active', 'is_staff', 'is_superuser', 'groups')}), (_('Important dates'), {'fields': ('last_login', 'date_joined')}), ) self.add_fieldsets = ((None, {'classes': ('wide',), 'fields': ('username', 'name', 'password1', 'password2', 'email', 'is_active', 'is_staff', 'is_superuser', 'groups'), }), ) return super(CustomUserAdmin, self).changelist_view(request, extra_context) admin.site.register(models.MyUser, CustomUserAdmin) # 註冊一下 admin.site.register(models.User_ex, User_exAdmin)
首頁面
設定組權限管理
編輯用戶頁面
管理員:
非管理員:(沒有設定超級用戶的權限)
新增用戶頁面
ui
經過以上,基本能夠實現一個用戶管理後臺的需求了。this
https://simpleisbetterthancomplex.com/tutorial/2016/07/22/how-to-extend-django-user-model.html#proxy
http://www.cnblogs.com/daliangtou/p/5435385.html
https://docs.djangoproject.com/en/1.9/topics/auth/customizing/#django.contrib.auth.models.PermissionsMixin.has_perms3d