替代 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 添加数据库字段备注来实现项目的定制化。这不仅增强了你的项目的灵活性,也提高了数据库的可读性。希望本文能为你的开发工作提供帮助,如果你在开发过程中遇到了类似的需求,记得分享你的经验!

相关推荐
代码中の快捷键4 分钟前
MySQL数据库存储引擎
数据库·mysql
只因在人海中多看了你一眼4 分钟前
数据库体系
数据库
尘浮生26 分钟前
Java项目实战II基于微信小程序的电影院买票选座系统(开发文档+数据库+源码)
java·开发语言·数据库·微信小程序·小程序·maven·intellij-idea
六月闻君40 分钟前
MySQL 报错:1137 - Can‘t reopen table
数据库·mysql
SelectDB技术团队1 小时前
兼顾高性能与低成本,浅析 Apache Doris 异步物化视图原理及典型场景
大数据·数据库·数据仓库·数据分析·doris
inventecsh1 小时前
mongodb基础操作
数据库·mongodb
白云如幻1 小时前
SQL99版链接查询语法
数据库·sql·mysql
Lucky小小吴1 小时前
有关django、python版本、sqlite3版本冲突问题
python·django·sqlite
爱吃烤鸡翅的酸菜鱼1 小时前
MySQL初学之旅(4)表的设计
数据库·sql·mysql·database
计算机毕设指导62 小时前
基于 SpringBoot 的作业管理系统【附源码】
java·vue.js·spring boot·后端·mysql·spring·intellij-idea