Django User模型

news2024/10/7 12:18:03

Django User模型

    • 用户管理
      • 自定义用户模型
      • Django自定义验证
      • 引用User模型
      • 视图开发
        • 创建序列器
        • 创建视图
        • 创建路由
    • 用户注册
      • 注册序列化器
      • 注册视图
      • 注册路由

用户管理

在开发登录功能的时候需要数据库来保存用户登录信息和状态,Django中有个内置app 名为 django.contrib.auth ,缺省包含在项目Installed App设置中。

这个app 的 models 定义中包含了一张 用户表,名为 auth_user 。当执行 migrate 创建数据库表时,就创建了 用户表 auth_user ,这张用户表包含的字段有:

在这里插入图片描述

自定义用户模型

Django 内置app django.contrib.auth 已经做好了登录验证功能。如果用户表 auth_user的字段足够在项目中使用,那么直接使用默认User模型即可。

如果用户表 auth_user的字段不符合项目的需求,需要重新定义,例如需要新增一些字段,像真实姓名、手机号、用户类型等,推荐的方式是通过继承 django.contrib.auth.models 里面的 AbstractUser 类的方式。

千万不要去改 Django 内置模块 contrib.auth.models 里面的类定义,如果改动源码,那么项目就依赖当前库,如果更新了库或者环境移植重写装库,那原来的代码就失效了

models 包下新增一个 auth.py文件

from django.contrib.auth.models import AbstractUser
from django.db import models


class User(AbstractUser):
    usertype = (
        (0, '开发'),
        (1, '测试'),
        (2, '需求'),
        (3, '运维'),
    )
    realname = models.CharField(max_length=32, verbose_name='真实姓名')
    phone = models.CharField(max_length=11, unique=True, null=True, blank=True, verbose_name='手机号')
    user_tpye = models.SmallIntegerField(choices=usertype, default=0, verbose_name='用户类型')

这样就在原来的 contrib.auth 里面的 user表的基础上 新增了 usertype、realname、phone 这些字段

Django自定义验证

然后需要告诉Django,使用这个表作为 系统的 user表

models 包下的 __init__.py 文件中导入User模型

from .hr3 import Step,Case,Config,Request
from .mgr import Enviroment,Project
from .auth import User 	# 导入User模型

settings.py 文件底部,添加如下代码进行设置

AUTH_USER_MODEL = 'sqtp.User'

其中 sqtp 为定义 User 所在的 django app 名称,一定要确保这个 sqtp 在在settings.py 文件中的 INSTALLED_APPS 里面设置了。

将修改同步至数据库

python manage.py makemigrations
python manage.py migrate

可能会遇到

ValueError: The field admin.LogEntry.user was declared with a lazy reference to 'sqtp.user', but app 'sqtp' doesn't provide model 'user'.

这个错误是由于原有的用户模型被依赖,使用自定义会改变依赖关系,这个改动并不能自动完成,需要手动修复架构,将数据从旧的用户表移出,并有可能需要手动执行一些迁移操作。

由于 Django 对可交换模型的动态依赖特性的限制, AUTH_USER_MODEL 所引用的模型必须在其应用的第一次迁移中创建(通常称为 0001_initial );否则,会出现依赖问题。

所以,需要先删除migrations目录所有文件,然后再删除数据库并重写创建。再执行迁移动作就可以了。

执行迁移命令后,sqtp_user表中新增了 usertype、realname、phone 这些字段,且伴随着sqtp_user表的创建成功,会新增sqtp_user_groupssqtp_user_user_permissions两个表,一个是用户组,一个是用户权限

在这里插入图片描述

引用User模型

用户模型创建好之后,其他模型需要关联的部分就可以加上了。首先是Project,增加项目管理员admin 和成员 members,关联了同一个模型,需要设置反向查询名 related_name

如果直接引用User模型,那么以后项目改成不同的用户模型时就无法自动切到 AUTH_USER_MODEL 配置的用户模型,代码的可复用性就大打折扣了。因此应该直接引用 AUTH_USER_MODEL 配置的用户模型

mgr.py 中的项目类模型进行修改

# 存放所有项目管理相关模型

from django.db import models
from .base import CommonInfo
from django.conf import settings    # 导入setting文件中配置的内容

# 定义项目类
class Project(CommonInfo):
    Pro_Status = (
        ('developing','开发中'),
        ('operating','维护中'),
        ('stable','稳定运行中'),
        )
    # 引用 `AUTH_USER_MODEL` 配置的用户模型
    admin = models.ForeignKey(settings.AUTH_USER_MODEL,on_delete=models.DO_NOTHING,null=True,verbose_name='管理员',related_name='project_admin')
    members = models.ManyToManyField(settings.AUTH_USER_MODEL,verbose_name='项目成员',related_name='project_members')
    
    name = models.CharField(max_length=32,unique=True,verbose_name='项目名称')
    status = models.CharField(max_length=32,choices=Pro_Status,default='stable',verbose_name='项目状态')
    version = models.CharField(max_length=32,default='V1.0',verbose_name='版本')

    # 模型元类
    class Meta(CommonInfo.Meta): # 元类也需要显示继承父类的元类才会生效
        db_table = 'Project'  # 如果不设置,默认的名称是 app名_模型名
        verbose_name = '项目表'  # 表的对外显示名称

接下来是通用表中的创建者和更新者字段

base.py 中的公共模型进行修改

# 公共模型

from django.db import models
from django.conf import settings    # 导入setting文件中配置的内容

class CommonInfo(models.Model):
    # 公共字段部分: 创建时间、更新时间、描述
    create_time = models.DateTimeField(auto_now_add=True,verbose_name='创建时间',null=True)
    # auto_now_add 第一次创建数据时自动添加当前时间
    update_time = models.DateTimeField(auto_now=True,verbose_name='更新时间',null=True)
    # auto_now 每次更新数据时自动添加当前时间
    desc = models.TextField(null=True,blank=True,verbose_name='描述')

    create_by = models.ForeignKey(settings.AUTH_USER_MODEL,on_delete=models.DO_NOTHING,null=True,verbose_name='创建者',related_name='create_member')
    update_by = models.ForeignKey(settings.AUTH_USER_MODEL,on_delete=models.DO_NOTHING,null=True,verbose_name='更新者',related_name='update_member')

    def __str__(self):
        # 判断当前数据对象是否有name属性,如果有,返回name,如果没有,返回描述
        if hasattr(self,'name'):    # hasattr 是Python中是反射的一种用法
            return self.name
        else:
            return self.desc

    class Meta:
        abstract =True  # 定义抽象表,不会创建数据库表
        ordering = ['id']  # 根据id排序(默认为顺序排序)

将修改同步至数据库

python manage.py makemigrations
python manage.py migrate

会产生报错

sqtp.Case.create_by: (fields.E304) Reverse accessor for 'sqtp.Case.create_by' clashes with reverse accessor for 'sqtp.Config.create_by'.
        HINT: Add or change a related_name argument to the definition for 'sqtp.Case.create_by' or 'sqtp.Config.create_by'.

如果在抽象基类中存在ForeignKey或者ManyToManyField字段,并且使用了 related_name 或者related_query_name 参数,那么一定要小心。因为按照默认规则,每一个子类都将拥有同样的字段,这显然会导致错误。为了解决这个问题,当在抽象基类中使用 related_name 或者 related_query_name 参数时,它们两者的值中应该包含 %(app_label)s%(class)s 部分

  • %(class)s 用字段所属子类的小写名替换
  • %(app_label)s 用子类所属app的小写名替换

父类的字段被子类继承,都使用了相同的反向查询名,者显然是不行的,所以利用 %(app_label)s%(class)s 让子类继承的字段可以自由替换反向查询名

base.py 中的公共模型进行修改

# 公共模型

from django.db import models
from django.conf import settings    # 导入setting文件中配置的内容

class CommonInfo(models.Model):
    # 公共字段部分: 创建时间、更新时间、描述
    create_time = models.DateTimeField(auto_now_add=True,verbose_name='创建时间',null=True)
    # auto_now_add 第一次创建数据时自动添加当前时间
    update_time = models.DateTimeField(auto_now=True,verbose_name='更新时间',null=True)
    # auto_now 每次更新数据时自动添加当前时间
    desc = models.TextField(null=True,blank=True,verbose_name='描述')

    create_by = models.ForeignKey(settings.AUTH_USER_MODEL,on_delete=models.DO_NOTHING,null=True,verbose_name='创建者',related_name='create_member')
    update_by = models.ForeignKey(settings.AUTH_USER_MODEL,on_delete=models.DO_NOTHING,null=True,verbose_name='更新者',related_name='update_member')

    def __str__(self):
        # 判断当前数据对象是否有name属性,如果有,返回name,如果没有,返回描述
        if hasattr(self,'name'):    # hasattr 是Python中是反射的一种用法
            return self.name
        else:
            return self.desc

    class Meta:
        abstract =True  # 定义抽象表,不会创建数据库表
        ordering = ['id']  # 根据id排序(默认为顺序排序)

将修改同步至数据库

python manage.py makemigrations
python manage.py migrate

此时就可以同步成功了

视图开发

采用REST框架开发项目管理和用户管理

创建序列器

sqtp应用目录下的serializers.py文件中添加代码

from rest_framework import serializers
from sqtp.models import Config,Case,Step,Request,Enviroment,Project,User

# 项目部分序列化器
class ProjectSerializer(serializers.ModelSerializer):
    class Meta:
        model = Project
        fields = '__all__'


# 环境部分序列化器
class EnviromentSerializer(serializers.ModelSerializer):
    class Meta:
        model = Project
        fields = '__all__'

        
# 用户部分序列化器
class UserSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = '__all__'

创建视图

sqtp应用目录下的views.py文件中添加代码

from sqtp.models import Request,Case,Config,Step,Enviroment,Project     # 模型
from sqtp.serializers import RequestSerializer,CaseSerializer,StepSerializer,ConfigSerializer,EnviromentSerializer,ProjectSerializer    # 自定义的序列化类


class ProjectViewSet(viewsets.ModelViewSet):
    queryset = Project.objects.all()
    serializer_class = ProjectSerializer


class EnviromentViewSet(viewsets.ModelViewSet):
    queryset = Enviroment.objects.all()
    serializer_class = EnviromentSerializer
    
    
# 用户
@api_view(['GET'])
def user_list(request):
    query_set = User.objects.all()
    serializer = UserSerializer(query_set,many=True)
    return Response(serializer.data)


@api_view(['GET'])
def user_detail(request,_id):
    try:
        req_obj = User.objects.get(pk=_id)
    except User.DoesNotExist:
        return Response(status=status.HTTP_404_NOT_FOUND)
    serializer = UserSerializer(req_obj)
    return Response(serializer.data)

创建路由

sqtp应用目录下的urls.py文件中添加代码

router = DefaultRouter()
router.register(r'requests',sqtp_view.RequestViewSet)  
router.register(r'cases',sqtp_view.CaseViewSet)   
router.register(r'steps',sqtp_view.StepViewSet)  
router.register(r'project',sqtp_view.ProjectViewSet)  # 将Project视图信息注册路由列表
router.register(r'envs',sqtp_view.EnviromentViewSet)  # 将Enviroment视图信息注册路由列表

urlpatterns = [
    path('',include(router.urls)),
    path('swagger/',schema_view.with_ui('swagger',cache_timeout=0),name='schema-swagger-ui'),   #互动模式
    path('redoc/',schema_view.with_ui('redoc',cache_timeout=0),name='schema-redoc'),   #文档模式
    path('users/',sqtp_view.user_list),
    path('users/<int:_id>',sqtp_view.user_detail),
]

用户注册

用户认证机制的核心内容是用户模型,而用户认证机制首先要实现的就是用户注册功能–创建用户。

不同系统有不同的注册流程,但是大体上都差不都,都是提交信息给服务器,然后服务器判断没有问题后创建用户。注册流程可以参考下图

在这里插入图片描述

结合REST框架帮助我们完成验证的工作

注册序列化器

sqtp应用目录下的serializers.py文件中新增注册序列化器

# 注册序列化器
class RegisrerSerializer(serializers.ModelSerializer):
    # admin_code 不在User字段中,需要单独定义
    admin_code = serializers.CharField(default='')
    class Meta:
        model = User
        fields = ['username','password','email','phone','realname','admin_code']

    # 校验入参是否合法
    def validate(self, attrs):  # attrs为入参的字典形式
        if attrs.get('admin_code') and attrs['admin_code'] != 'sqtp_code':
            raise ValidationError('错误的admin_code')
        return attrs

    # 重写序列化器的保存方法
    def register(self):
        # 入参内容
        in_param = self.data
        # 入参内容是否有传 admin_code
        if 'admin_code' in in_param and in_param['admin_code'] == 'sqtp_code':
            in_param.pop('admin_code')  # 创建用户数据不需要admin_code,校验通过即可,需要将这个数据剔除出去
            # 创建管理员
            user = User.objects.create_superuser(**in_param) # 将数据进行解包,创建管理员
        else:
            in_param.pop('admin_code')
            user = User.objects.create_user(**in_param) # 将数据进行解包,创建普通用户
        return user

注册视图

sqtp应用目录下的views.py文件中新增注册视图

from sqtp.serializers import RequestSerializer, CaseSerializer, StepSerializer, ConfigSerializer, EnviromentSerializer, \
    ProjectSerializer, UserSerializer, RegisrerSerializer  # 自定义的序列化类
from django.contrib import auth     # 导入django自带的auth模块

@api_view(['POST'])
def register(request):
    # 获取序列化器
    serializer = RegisrerSerializer(data=request.data)
    if serializer.is_valid():    #自动根据模型定义来判断数据入参是否合法
        user = serializer.register()    # 创建用户数据
        auth.login(request,user)    # 完成用户登录状态的设置
        return Response(data={'msg':'register success','is_admin':user.is_superuser,'retcode':status.HTTP_201_CREATED},status=status.HTTP_201_CREATED)
    return Response(data={'msg':'error','retcode':status.HTTP_400_BAD_REQUEST,'error':serializer.errors},status=status.HTTP_400_BAD_REQUEST)
    

注册路由

sqtp应用目录下的urls.py文件中新增路由

urlpatterns = [
    path('',include(router.urls)),
    path('swagger/',schema_view.with_ui('swagger',cache_timeout=0),name='schema-swagger-ui'),   #互动模式
    path('redoc/',schema_view.with_ui('redoc',cache_timeout=0),name='schema-redoc'),   #文档模式
    path('users/',sqtp_view.user_list),
    path('users/<int:_id>',sqtp_view.user_detail),
    path('register/',sqtp_view.register),   # 注册
]

在浏览器中输入http://127.0.0.1:8888/register.html,进入注册页面,输入注册信息创建账户

在这里插入图片描述

可以看到数据库sqtp_user表中新增了一条用户数据

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/195564.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ICT是什么

信息与通信技术&#xff08;ICT&#xff0c;information and communications technology&#xff09;是一个涵盖性术语&#xff0c;覆盖了所有通信设备或应用软件&#xff1a;比如说&#xff0c;收音机、电视、移动电话、计算机、网络硬件和软件、卫星系统&#xff0c;等等&…

(1)Nginx简介和安装教程

目录 一、下载 二、报错提醒&环境安装 1、安装gcc编译器 2、安装perl库 3、安装 zlib库 4、也可通过命令进行统一安装 三、编译及安装 四、启动并访问 1、启动 2、访问 3、问题排查 五、安装成系统文件 一、下载 官网地址&#xff1a;nginx news Nginx官网提供…

OAuth2入门

1.下载资源 演示代码&#xff1a; OAuth2-example: 演示OAuth2的认证流程https://gitee.com/lisenaq/oauth2-example克隆下载到本地&#xff1a; 导入项目&#xff1a; client 客户 authorization-server 认证服务 resource-owner 资源所有者 resource-server 资源…

儿童台灯哪个品牌更护眼推荐?儿童书桌台灯品牌排行榜

不难发现&#xff0c;近些年我国儿童近视率增长迅速&#xff0c;随着生活条件越来越好&#xff0c;对电子章产品的普及非常广泛&#xff0c;每个家庭的孩子必不可少的就是伏案完成作业&#xff0c;这样的话就需要使用到台灯&#xff0c;选购台灯的时候最好选择适合儿童的专业护…

【算法基础】高精度加法

&#x1f466;个人主页&#xff1a;Weraphael ✍&#x1f3fb;作者简介&#xff1a;目前是C语言学习者 ✈️专栏&#xff1a;【C/C】算法 &#x1f40b; 希望大家多多支持&#xff0c;咱一起进步&#xff01;&#x1f601; 如果文章对你有帮助的话 欢迎 评论&#x1f4ac; 点赞…

一篇五分生信临床模型预测文章代码复现——FIgure 9.列线图构建,ROC分析,DCA分析 (三)

之前讲过临床模型预测的专栏,但那只是基础版本,下面我们以自噬相关基因为例子,模仿一篇五分文章,将图和代码复现出来,学会本专栏课程,可以具备发一篇五分左右文章的水平: 本专栏目录如下: Figure 1:差异表达基因及预后基因筛选(图片仅供参考) Figure 2. 生存分析,…

axios实战学习——使用高德地图api接口数据实现天气查询案例

文章目录&#x1f4cb;前言&#x1f3af;案例介绍&#x1f9e9;关于高德开发平台1️⃣创建应用生成Key2️⃣查看API文档&#x1f9e9;测试接口&#x1f3af;案例编写&#x1f3af;实现效果&#x1f4cb;前言 关于这个Vue axios 获取接口数据的操作&#xff0c;这篇文章就不过…

UniRx之基础入门

什么是Rx 官方ReactiveX简介&#xff1a; An API for asynchronous programming with observable streams。 通过这句话我们可以得到&#xff1a; 1.首先Rx是个编程接口&#xff0c;不同语言提供不同实现。例如JVM语言中的RxJava。 2.使用场景&#xff0c;异步编程中。 3.基…

路由器 内核开发 流程

宽 带上网已经不是什么新鲜事情&#xff0c;人们对相关的网络器件已经不再陌生&#xff0c;比如说常见的路由器。对于一般的网络用户&#xff0c;他们能知道怎样使用路由器来上网、玩游戏等就 已经感到很满足了&#xff0c;通常情况下对路由器的深层技术很少去过问研究&#xf…

Matlab和PCL中的点云滤波

而在PCL中总结了几种需要进行点云滤波处理的情况&#xff0c;这几种情况分别是&#xff1a; (1)点云数据密度不规则需要平滑。 (2)因为遮挡等问题造成离群点需要去除。 (3)大量数据需要进行“下采样”(Downsample)。 (4)噪声数据需要去除。 对应的解决方法是&#xff1a; (1)按…

什么是ITIL中的变更管理

商业环境和客户期望在不断变化&#xff0c;数字化转型已成为各行各业企业成功的关键因素。数字化转型的关键在于利用可用 应对业务挑战和抓住机遇的技术。当你分解它时&#xff0c;数字化转型基本上是信息技术管理更好地消除有问题的领域&#xff0c;并使您的 IT 基础架构能够应…

WebView缓存机制

一 前言 由于H5具备 开发周期短、灵活性好 的特点&#xff0c;所以现在 Android App大多嵌入了 Android Webview 组件进行 Hybrid 开发 但我知道你一定在烦恼 Android Webview 的性能问题&#xff0c;特别突出的是&#xff1a;加载速度慢 & 消耗流量 今天&#xff0c;我将…

Django 模型的继承

Django 模型的继承项目管理模型关联关系模块的包管理模型的继承项目管理 到目前为止&#xff0c;都是属于httprunner中的用例部分&#xff0c;针对核心功能进行的开发工作&#xff0c;要把平台做成一个用户可以使用的程度还需要些额外的功能&#xff0c;比如项目管理&#xff…

13薪| 8k-14k Java开发工程师

"众推职聘”以交付结果为宗旨的全流程化招聘服务平台&#xff01;今日招聘信息↓工作内容1.参与软件项目和产品概要设计&#xff0c;负责详细功能设计、编码实现及相关文档编写&#xff1b;2.根据模块设计完成相应的模块编码及单元测试&#xff1b;3.对用户行为、需求及反…

zeek集群简述

Zeek不是多线程的&#xff0c;因此&#xff0c;一旦达到单处理器内核的限制&#xff0c;当前唯一的选择就是将工作负载分散到多个内核&#xff0c;甚至多个物理计算机上。Zeek的集群部署场景是构建这些大型系统的当前解决方案。Zeek附带的工具和脚本提供了一种结构&#xff0c;…

自注意力和位置编码(比较卷积神经网络、循环神经网络和自注意力)

在自注意力中&#xff0c;查询、键和值都来自同一组输入。 卷积神经网络和自注意力都拥有并行计算的优势&#xff0c;而且自注意力的最大路径长度最短。但是因为其计算复杂度是关于序列长度的二次方&#xff0c;所以在很长的序列中计算会非常慢。 为了使用序列的顺序信息&…

Nostr with NIP-05 Verification Guide

What is a NIPNIPs (Nostr Implementation Possibilities) document what MUST, what SHOULD and what MAY be implemented by Nostr-compatible relay and client software. See a complete list of nips here.NIP-05 提案是针对用户 Nostr 帐户的验证方法&#xff0c;可以将其…

The update is not applicable to your computer

在安装windows CVE-2022-44698补丁的时候出现了报错&#xff0c;"Windows Update Standalone Installer The update is not applicable to your computer" 1.找到漏洞对应的官方文章 CVE-2022-44698 - Security Update Guide - Microsoft - Windows SmartScreen S…

学术科研无从下手?27 条机器学习避坑指南,让你的论文发表少走弯路

内容一览&#xff1a;如果你刚接触机器学习不久&#xff0c;并且未来希望在该领域开展学术研究&#xff0c;那么这份为你量身打造的「避坑指南」可千万不要错过了。 关键词&#xff1a;机器学习 科研规范 学术研究 机器学习学术小白&#xff0c;如何优雅避坑坑、让自己的论文顺…

力扣sql简单篇练习(九)

力扣sql简单篇练习(九) 1 合作过至少三次的演员和导演 1.1 题目内容 1.1.1 基本题目信息 1.1.2 示例输入输出 1.2 示例sql语句 SELECT actor_id,director_id FROM ActorDirector GROUP BY actor_id,director_id HAVING count(timestamp)>31.3 运行截图 2 患某种疾病的患…