caseast

前言

参考上篇博文,我们利用了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的工作模式和源码,怎么取舍还看自己的需求了。

代码实现

扩展User的方法大概有4种,参考这个国外博客:https://simpleisbetterthancomplex.com/tutorial/2016/07/22/how-to-extend-django-user-model.html#proxy ,我用的是里边描述的第四种方法。
models.py

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类部分源码

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.py

AUTH_USER_MODEL = "web_sso.MyUser"  # 我们的app叫web_sso,这个MyUser就是models定义的那个类

看下扩展完的效果,可以看到,我们不用再像之前一样维护“用户”和“用户详情”两张表了,但还是有很多小问题需要解决。

长话短说,直接看一下,我的admin.py改了哪些东西吧.
admin.py

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)


效果展示

首页面

设定组权限管理

编辑用户页面
管理员:

非管理员:(没有设定超级用户的权限)

新增用户页面

通过以上,基本可以实现一个用户管理后台的需求了。

参考资料

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_perms

分类:

技术点:

相关文章:

  • 2021-08-14
  • 2021-05-14
  • 2022-01-20
  • 2019-01-23
  • 2021-05-19
  • 2021-12-28
  • 2021-04-14
  • 2021-12-01
猜你喜欢
  • 2021-12-15
  • 2019-03-19
  • 2021-11-01
  • 2021-10-19
  • 2021-12-22
  • 2021-04-04
相关资源
相似解决方案