文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

django之对django内置的User模型进行自定义扩展方式

2023-05-12 14:17

关注

问题

实际开发中可能内置User模型的字段不能满足需要。

解决

1.首先查看内置User模型的源码:

MyDjango\venv\Scripts\pyton.exe\Lib\site-packages\django\contrib\auth\models.py,理清相关各类继承关系,如下:

class PermissionsMixin(models.Model):
class AbstractUser(AbstractBaseUser, PermissionsMixin):
class User(AbstractUser):

其中AbstractBaseUser在文件MyDjango\venv\Scripts\pyton.exe\Lib\site-packages\django\contrib\auth\base_user.py中:

class AbstractBaseUser(models.Model):

官方文档可以知道,User具有如下的内置方法:

class models.User
get_username()¶
Returns the username for the user. Since the User model can be swapped out, you should use this method instead of referencing the username attribute directly.
get_full_name()¶
Returns the first_name plus the last_name, with a space in between.
get_short_name()¶
Returns the first_name.
set_password(raw_password)¶
Sets the user's password to the given raw string, taking care of the password hashing. Doesn't save the User object.
When the raw_password is None, the password will be set to an unusable password, as if set_unusable_password() were used.
check_password(raw_password)¶
Returns True if the given raw string is the correct password for the user. (This takes care of the password hashing in making the comparison.)
set_unusable_password()¶
Marks the user as having no password set. This isn't the same as having a blank string for a password. check_password() for this user will never return True. Doesn't save the User object.
You may need this if authentication for your application takes place against an existing external source such as an LDAP directory.
has_usable_password()¶
Returns False if set_unusable_password() has been called for this user.
Changed in Django 2.1:
In older versions, this also returns False if the password is None or an empty string, or if the password uses a hasher that's not in the PASSWORD_HASHERS setting. That behavior is considered a bug as it prevents users with such passwords from requesting a password reset.
get_group_permissions(obj=None)¶
Returns a set of permission strings that the user has, through their groups.
If obj is passed in, only returns the group permissions for this specific object.
get_all_permissions(obj=None)¶
Returns a set of permission strings that the user has, both through group and user permissions.
If obj is passed in, only returns the permissions for this specific object.
has_perm(perm, obj=None)¶
Returns True if the user has the specified permission, where perm is in the format "<app label>.<permission codename>". (see documentation on permissions). If the user is inactive, this method will always return False.
If obj is passed in, this method won't check for a permission for the model, but for this specific object.
has_perms(perm_list, obj=None)¶
Returns True if the user has each of the specified permissions, where each perm is in the format "<app label>.<permission codename>". If the user is inactive, this method will always return False.
If obj is passed in, this method won't check for permissions for the model, but for the specific object.
has_module_perms(package_name)¶
Returns True if the user has any permissions in the given package (the Django app label). If the user is inactive, this method will always return False.
email_user(subject, message, from_email=None, **kwargs)¶
Sends an email to the user. If from_email is None, Django uses the DEFAULT_FROM_EMAIL. Any **kwargs are passed to the underlying send_mail() call.

从源码可以知道,它们来自PermissionsMixin类、AbstractBaseUser类和AbstractUser类。

2.因此要实现内置User模型的扩展

可以从这些继承关系入手:

查看源码可以知道,User直接继承自AbstractUser,如果AbstractUser拥有的方法已经够用,且仅仅是添加一些额外字段的话,这是最方便的方法。

查看源码可以知道,AbstractUser继承自AbstractBaseUser与PermissionsMixin。这方法比方法1自定义程度更高,对已经使用User建表的情况不友好,因为会破坏已有的表结构,且还要自己写相关的权限验证,相当麻烦。

可以是可以,但直接改源码会在版本升级时失效。

不改变已有的表结构,且如果AbstractUser拥有的方法已经够用,仅需在已有表基础上添加额外字段,就可以将这些额外字段所在的表通过外键与 User 关联起来。

自定义一个继承自User的类,将元数据Meta中的proxy置为True,以代表这个是User的代理模型。适用于不改变已有的表结构,但对User拥有的方法不够满足而需要自定义方法的情况。

大多情况下会选择方法1,既不改变原有User结构,也不会额外建表。

如下:

from django.db import models
from django.contrib.auth.models import AbstractUser
class MyUser(AbstractUser):
    qq = models.CharField('QQ号', max_length=30)
    wechat = models.CharField('微信号', max_length=40)
    mobile = models.CharField('电话号', max_length=20)
    class Meta:
        verbose_name_plural = '自定义用户表'
    def __str__(self):
        return self.username

记得在settings.py添加:

AUTH_USER_MODEL = '应用名.扩展的类名'

最后要进行数据迁移:

python manage.py makemigrations
python manage.py migrate

可能会报错:

django.db.migrations.exceptions.InconsistentMigrationHistory:
Migration admin.0001_initial is applied bef ore its dependency
user.0001_initial on database ‘default’.

删除数据库中除auth_user外的其他表,再重新进行数据迁移即可。

结果如下:

进入admin后台系统,但却没显示MyUser信息表。

根据MyUser的产生原理可以知道,MyUser是在User的model.py中定义的,admin后台无法直接显示MyUser信息表,需要在项目的admin.py与__init__.py中进行相关定义:

admin.py:
from django.contrib import admin
from .models import MyUser
from django.contrib.auth.admin import UserAdmin
from django.utils.translation import gettext_lazy as _
# 先注册
@admin.register(MyUser)
class MyUserAdmin(UserAdmin):
    list_display = ['username', 'email', 'mobile', 'qq', 'wechat']
    # 将源码的UserAdmin.fieldsets转换成列表格式
    fieldsets = list(UserAdmin.fieldsets)
    fieldsets[1] = (_('Personal info'),
                    {'fields': ('first_name', 'last_name',
                     'email', 'mobile', 'qq', 'wechat')})
__init__.py:
from django.apps import AppConfig
import os
default_app_config = 'user.IndexConfig'
# 获取当前app的命名
def get_current_app_name(_file):
    return os.path.split(os.path.dirname(_file))[-1]
# 重写类IndexConfig
class IndexConfig(AppConfig):
    name = get_current_app_name(__file__)
    verbose_name = '自定义用户信息数据表'

MyUserAdmin继承自UserAdmin,再重写后台数据展示字段,就能使自定义用户模型展示在admin后台。

然后运行开发服务器,可能会报错:

LookupError: No installed app with label ‘admin’.

我的django版本为2.2,查了一下,据说是2.2的bug,更换为2.2.14后问题解决。

如下:

访问127.0.0.1:8000

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持编程网。

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯