参考上篇博文,咱们利用了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