替代 Django 默认 User 模型并使用 `django-mysql` 添加数据库备注20240904

替代 Django 默认 User 模型并使用 django-mysql 添加数据库备注

前言

在 Django 项目开发中,默认的 User 模型虽然能够满足许多基础需求,但在实际项目中我们常常需要对用户模型进行定制化。通过覆盖默认的 User 模型,我们可以根据具体的业务需求添加额外的字段、修改字段属性等。同时,使用 django-mysql,我们还可以在数据库迁移时为字段添加备注,提高数据库的可读性。

本文将详细讲解如何从头开始创建一个 Django 项目,替代默认的 User 模型,并使用 django-mysql 为数据库字段添加注释。

一、项目初始化

1. 创建 Django 项目

首先,使用 django-admin 命令来创建一个新的 Django 项目:

bash 复制代码
django-admin startproject oaback
cd oaback

此命令将在当前目录下创建一个名为 oaback 的 Django 项目。oaback 目录将包含项目的基本结构。

2. 创建应用 oaauth

接下来,我们需要创建一个新的应用来管理用户认证和权限逻辑:

bash 复制代码
django-admin startapp oaauth

这个命令将在 oaback 目录下创建一个 oaauth 应用,该应用将包含用户模型及相关逻辑。

二、配置 settings.py

settings.py 中,我们需要配置已安装的应用程序,并覆盖默认的 User 模型。

1. 配置已安装的应用程序

打开 oaback/settings.py 文件,找到 INSTALLED_APPS,并添加以下配置:

python 复制代码
INSTALLED_APPS = [
    # "django.contrib.admin",
    "django.contrib.auth",
    "django.contrib.contenttypes",
    # "django.contrib.sessions",
    # "django.contrib.messages",
    "django.contrib.staticfiles",
    # 安装rest_framework
    "rest_framework",
    # 为了解决跨域问题,安装corsheaders
    "corsheaders",
    "django_mysql",  # 添加 django-mysql 到已安装的应用程序中
    # 项目app
    "apps.oaauth",  # 你的用户管理应用
    "apps.absent"   # 其他应用
]
2. 设置自定义用户模型

为了使用自定义的用户模型,必须在 settings.py 中配置 AUTH_USER_MODEL。确保添加如下配置:

python 复制代码
# OAUser覆盖原有的User模型
# 正确的格式app.User
AUTH_USER_MODEL = 'oaauth.OAUser'

三、定义自定义 User 模型

oaauth/models.py 文件中,定义自定义的用户模型:

python 复制代码
from django.contrib.auth.hashers import make_password
from django.db import models
from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin, BaseUserManager
from shortuuidfield import ShortUUIDField
from django_mysql.models import Model

class UserStatusChoices(models.IntegerChoices):
    ACTIVED = 1, "已激活"
    UNACTIE = 2, "未激活"
    LOCKED = 3, "已锁定"

class OAUserManager(BaseUserManager):
    use_in_migrations = True

    def _create_user(self, real_name, email, password, **extra_fields):
        if not real_name:
            raise ValueError("The given real_name must be set")
        email = self.normalize_email(email)

        user = self.model(real_name=real_name, email=email, **extra_fields)
        user.password = make_password(password)
        user.save(using=self._db)
        return user

    def create_user(self, real_name, email=None, password=None, **extra_fields):
        extra_fields.setdefault("is_staff", True)
        extra_fields.setdefault("is_superuser", False)
        return self._create_user(real_name, email, password, **extra_fields)

    def create_superuser(self, real_name, email=None, password=None, **extra_fields):
        extra_fields.setdefault("is_staff", True)
        extra_fields.setdefault("is_superuser", True)
        extra_fields.setdefault("status", UserStatusChoices.ACTIVED)

        if extra_fields.get("is_staff") is not True:
            raise ValueError("Superuser must have is_staff=True.")
        if extra_fields.get("is_superuser") is not True:
            raise ValueError("Superuser must have is_superuser=True.")

        return self._create_user(real_name, email, password, **extra_fields)


class OAUser(Model, AbstractBaseUser, PermissionsMixin):
    uid = ShortUUIDField(
        primary_key=True,
        verbose_name="用户ID",
        help_text="用户唯一标识符,使用ShortUUID生成",
        db_comment="用户唯一标识符,使用ShortUUID生成"
    )
    password = models.CharField(
        max_length=128,
        verbose_name="密码",
        help_text="用户的密码,已加密存储",
        db_comment="用户的密码,已加密存储"
    )
    last_login = models.DateTimeField(
        verbose_name="上次登录时间",
        help_text="用户上次登录的日期和时间",
        db_comment="用户上次登录的日期和时间",
        null=True,
        blank=True
    )
    is_superuser = models.BooleanField(
        verbose_name="超级用户状态",
        help_text="标识用户是否具有所有权限",
        db_comment="标识用户是否具有所有权限",
        default=False
    )
    real_name = models.CharField(
        max_length=150,
        verbose_name="真实姓名",
        help_text="用户的真实姓名,最多150个字符",
        db_comment="用户的真实姓名,最多150个字符"
    )
    email = models.EmailField(
        unique=True,
        blank=False,
        verbose_name="电子邮件",
        help_text="用户的电子邮件地址,必须唯一",
        db_comment="用户的电子邮件地址,必须唯一"
    )
    telephone = models.CharField(
        max_length=20,
        unique=True,
        blank=False,
        verbose_name="联系电话",
        help_text="用户的联系电话,必须唯一,最多20个字符",
        db_comment="用户的联系电话,必须唯一,最多20个字符"
    )
    is_staff = models.BooleanField(
        default=False,
        verbose_name="员工状态",
        help_text="是否为员工身份,员工可访问管理界面",
        db_comment="是否为员工身份,员工可访问管理界面"
    )
    status = models.IntegerField(
        choices=UserStatusChoices.choices,
        default=UserStatusChoices.UNACTIE,
        verbose_name="用户状态",
        help_text="用户的当前状态",
        db_comment="用户的当前状态"
    )
    is_active = models.BooleanField(
        default=True,
        verbose_name="活跃状态",
        help_text="是否为活跃用户,影响登录权限",
        db_comment="是否为活跃用户,影响登录权限"
    )
    date_joined = models.DateTimeField(
        auto_now_add=True,
        verbose_name="加入日期",
        help_text="用户加入系统的日期和时间",
        db_comment="用户加入系统的日期和时间"
    )
    department = models.ForeignKey(
        "OADepartment",
        null=True,
        on_delete=models.SET_NULL,
        related_name="staffs",
        related_query_name="staffs",
        verbose_name="所属部门",
        help_text="用户所属的部门,可以为空。部门被删除时,该字段设置为空",
        db_comment="用户所属的部门,可以为空。部门被删除时,该字段设置为空"
    )
    extra_data = models.JSONField(
        verbose_name="额外数据",
        help_text="用户的额外信息,存储为JSON格式",
        default=dict,
        db_comment="用户的额外信息,存储为JSON格式"
    )

    objects = OAUserManager()

    EMAIL_FIELD = "email"
    USERNAME_FIELD = "email"
    REQUIRED_FIELDS = ["real_name", "password"]

    def clean(self):
        super().clean()
        self.email = self.__class__.objects.normalize_email(self.email)

    def get_full_name(self):
        return self.real_name

    def get_short_name(self):
        return self.real_name

    def __str__(self):
        return f"{self.real_name} ({self.email})"

    def get_status_display(self):
        return dict(UserStatusChoices.choices).get(self.status, "Unknown")

四、应用迁移并验证结果

1. 生成并应用迁移

在完成模型定义和 settings.py 配置后,运行以下命令生成并应用数据库迁移:

bash 复制代码
python manage.py makemigrations
python manage.py migrate
2. 验证数据库中的字段备注

应用迁移后,你可以使用数据库管理工具或直接运行 SQL 查询,来验证字段备注是否已成功应用:

sql 复制代码
SHOW FULL COLUMNS

 FROM oaauth_oauser;

结语

通过本文的学习,你已经掌握了如何从零开始创建一个 Django 项目,并通过替代默认的 User 模型和使用 django-mysql 添加数据库字段备注来实现项目的定制化。这不仅增强了你的项目的灵活性,也提高了数据库的可读性。希望本文能为你的开发工作提供帮助,如果你在开发过程中遇到了类似的需求,记得分享你的经验!

相关推荐
Mr.1334 分钟前
数据库的三范式是什么?
数据库
Cachel wood40 分钟前
python round四舍五入和decimal库精确四舍五入
java·linux·前端·数据库·vue.js·python·前端框架
Python之栈1 小时前
【无标题】
数据库·python·mysql
风_流沙1 小时前
java 对ElasticSearch数据库操作封装工具类(对你是否适用嘞)
java·数据库·elasticsearch
亽仒凣凣1 小时前
Windows安装Redis图文教程
数据库·windows·redis
亦世凡华、1 小时前
MySQL--》如何在MySQL中打造高效优化索引
数据库·经验分享·mysql·索引·性能分析
YashanDB1 小时前
【YashanDB知识库】Mybatis-Plus调用YashanDB怎么设置分页
数据库·yashandb·崖山数据库
ProtonBase1 小时前
如何从 0 到 1 ,打造全新一代分布式数据架构
java·网络·数据库·数据仓库·分布式·云原生·架构
云和数据.ChenGuang7 小时前
Django 应用安装脚本 – 如何将应用添加到 INSTALLED_APPS 设置中 原创
数据库·django·sqlite
woshilys7 小时前
sql server 查询对象的修改时间
运维·数据库·sqlserver