Python实现员工管理系统(Django页面版 ) 六

news2024/12/23 5:25:38

        本篇博客主要实现用户账号管理,这与之前的账号管理不同,之前的账号管理你可以理解为公司在外面买的一些手机号然后需要发放给员工做内部使用,而本篇博客的用户账号管理主要是为了后续的登录网页实现,那么我们开始今天的项目实现吧。

本次项目效果展示:

 

用户账号创建步骤:

1. 在models.py里面完成员工列表的数据表建立以及迁移操作

2. 根据需要实现的需求在urls.py配置好每个需求的url地址。

3 根据需求完成实现每个需求对应的函数板块

4. 完成页面展示

下面我们开始本篇博客的代码逻辑思路讲解:

用户账号的实现步骤

1. 数据表的建立以及迁移操作

首先我们先确定数据表的字段以及对应的一些字段约束

1. id:是每一条数据的主键,有Django默认自己生成,无需处理。

2. username:用户名,最大字长为32位

3. password:密码,最大字长为64位

4. level: 等级,用于确定该用户为哪种级别的用户,我们对不同级别的用户会有不同的页面展示

models.py:

class Admin(models.Model):
    username = models.CharField(verbose_name='用户名',max_length=32)
    password = models.CharField(verbose_name='密码',max_length=64)
    level_choice = (
        ('user','员工用户'),
        ('boss','领导用户'),
        ('admin','管理员')
    )
    role = models.CharField(verbose_name='角色',choices=level_choice,max_length=12,default='user')

 数据迁移操作:

 点击后依次输入 makemigrations 和 migrate 这样你的数据库数据迁移成功

 打开你的数据库确认一下,如果出现project_manage_admin这个新的表,那么你的表创建成功。

我们往数据表中插入一些数据,为了方便我们后续进行查看我们的方法组件是否成功实现。

下面我们开始我们的需求实现。

2. 需求实现

        在本篇项目中我们需要实现的是账号列表的可视化展示,账号添加,账号的删除和修改,翻页处理。

2.1 账号列表的可视化展示 和 翻页处理

        对于翻页处理我在上一篇博客中有写到,直接调用模块即可。

Python实现员工管理系统(Django页面版 ) 翻页封装-CSDN博客

我们在之前创建的views模块中新建一个admin.py文件,用于封装我们各个组件的方法。

        对于账号列表的展示代码其实和之前的员工列表和部门列表的展示是一样的,都是先获取到数据库中的所有数据,然后通过前端代码展示到界面上。

admin.py

from django.shortcuts import render, redirect
from project_manage import models
def admin_list(request):
    data_list = models.Admin.objects.all()
    page_object = Pagination(request,data_list)
    content = {
        'data_list':page_object.page_queryset,
        'page_string':page_object.page_html()
    }
    return render(request,'admin_list.html',content)

admin_list.html

{% extends 'layout.html' %}
{% block content %}
    <div class="container">
        <div style="margin-bottom: 10px">
            {# target="_blank" 重新打开一个页面 #}
            <a href="/admin/add/" class="btn btn-success">
                <span class="glyphicon glyphicon-plus" aria-hidden="true"></span> 新建账号</a>

        </div>
        <div class="panel panel-success">
            <div class="panel-heading">
                <h3 class="panel-title"><span class="glyphicon glyphicon-th-list" aria-hidden="true"></span>账号列表</h3>
            </div>
            <div class="panel-body">
                <table class="table">
                    <thead>
                    <tr>
                        <th>ID</th>
                        <th>身份</th>
                        <th>用户名</th>
                        <th>密码</th>
                        <th>重置密码</th>
                    </tr>
                    </thead>
                    <tbody>
                    {% for data in data_list %}
                        <tr>
                            <td>{{ data.id }}</td>
                            <td>{{ data.get_role_display }}</td>
                            <td>{{ data.username }}</td>
                            <td>**********</td>
                            <td><a href="/admin/{{ data.id }}/reset">重置</a></td>
                            <td>
                                {#                                <a href="/user/delete/?nid={{ data.id }}"><span class="glyphicon glyphicon-trash"#}
                                {#                                                                                aria-hidden="true"#}
                                {#                                                                                style="color: red"></span></a>#}
                                <a href="/admin/{{ data.id }}/delete"><span class="glyphicon glyphicon-trash"
                                                                            aria-hidden="true"
                                                                            style="color: red"></span></a>
                                <span>&nbsp;&nbsp;</span>
                                <a href="/admin/{{ data.id }}/modify"><span class="glyphicon glyphicon-new-window"
                                                                           aria-hidden="true"
                                                                           style="color: #2aabd2"></span></a>
                            </td>
                        </tr>
                    {% endfor %}

                    </tbody>
                </table>
            </div>
        </div>
        <ul class="pagination">
            {{ page_string }}
        </ul>
    </div>
{% endblock %}

 配置路由(URL)

    # 用户账号列表
    path('admin/list/', admin.admin_list),

layout.html

 

启动服务后点击用户账号,即可跳转到下面的界面,这样我们的用户账号列表即可完成。  

2.2 账号信息添加

        不知道大家有没有发现,我在对密码进行处理的时候是不会将用户的密码进行展示的,就算它是老板或者管理员用户,它也没有办法找到我的密码,那么这个时候可能你们会想,那我管理员在后台数据库不还是能看到你的数据吗?我们怎么可能这么不谨慎,我们不想给看到的怎么可能会给它看,下面我来介绍一种加密方式:md5加密。

MD5(Message Digest Algorithm 5)是一种被广泛使用的密码散列函数,用于将输入的任意长度的信息转换成固定长度的哈希值。它是由美国密码学家罗纳德·李维斯特(Ronald Rivest)设计的。

MD5加密算法可以将任意长度的消息转换为一个128位的固定长度输出,通常用一个32位的十六进制数表示。它具有以下特点:

  1. 不可逆性:MD5加密是不可逆的,即无法从加密后的哈希值还原出原始消息内容。这使得MD5非常适合用于密码存储,因为即使数据库泄露,攻击者也无法直接获取用户的明文密码。

  2. 唯一性:不同的输入会产生不同的MD5哈希值,即使原文只有一个字符的变化,输出的哈希值也会大不相同。这使得MD5可以用于校验文件的完整性。

  3. 快速性:MD5算法的计算速度非常快,对于任意长度的文本,都能够在很短的时间内生成其哈希值。

        我们可以看到MD5有不可逆性这个特点,这说明MD5很难被人破解,因此我们采用MD5进行加密是不是一个很好的方式。

我们随便新建一个测试py文件,编写一下我们的MD5加密方法

# -*- coding:utf-8 -*-
import hashlib
str = 'dasdfasf11231321'
def md5(data):
    obj_md5 = hashlib.md5(str.encode('utf-8'))
    obj_md5.update(data.encode('utf-8'))
    return obj_md5.hexdigest()

print(md5('123'))

 

这样我们就对我们的目标数据进行MD5加密成功,那么我们将这个运用到我们的项目之中。

我们在之前封装翻页方法的文件夹 utils 中新建一个一个py文件,名为 encryption

然后对我们编写MD5方法

# -*- coding:utf-8 -*-
import hashlib
from django.conf import settings

def md5(data):
    obj_md5 = hashlib.md5(settings.SECRET_KEY.encode('utf-8'))
    obj_md5.update(data.encode('utf-8'))
    return obj_md5.hexdigest()

        其中的settings.SECRET_KEY 是我们django提供的一个加密字符串,它在我们的setting.py文件中,我们通常导入settings这个模块不是通过根目录依次遍历导入,而是通过django提供的模块导入。

 由此我们对于数据的加密就完成了。

        我们在进行用户新建账号提交的时候是不是常常会遇到需要你提交一个再次确认密码,你得和你之前的密码保持一致你才能添加成功。针对以上我们需要注意的点,我们开始编写我们的项目代码。

        首先我们新建一个由model.form继承的类,用于对我们的字段数据进行一个约束,以及对我们提交的数据字段做一个钩子方法

钩子方法的介绍:

        Django钩子方法是指在Django框架中提供的一些回调方法,用于在特定的时间点执行一些自定义的逻辑。这些方法可以被开发者在自己的代码中覆盖或扩展,从而实现定制化的处理。

admin,py

from django import forms
from django.core.validators import ValidationError
from project_manage.utils.encryption import md5
class AdminModelForm(forms.ModelForm):
    # 新建字段confirm_password,数据库并不会有这个字段
    confirm_password = forms.CharField(label='确认密码',widget=forms.PasswordInput)
    class Meta:
        model = models.Admin
        # 只选取这三个字段
        fields = ['username','password','confirm_password']
        widgets = {
            # 对于password字段修改其输入框的方式
            'password': forms.PasswordInput(render_value=True)
        }

    def __init__(self,*args,**kwargs):
        super().__init__(*args,**kwargs)
        for name,field in self.fields.items():
            field.widget.attrs = {"class":"form-control"}

    def clean_password(self):
        pwd = self.cleaned_data.get('password')
        return md5(pwd)

    def clean_confirm_password(self):
        confirm = md5(self.cleaned_data.get('confirm_password'))
        pwd = self.cleaned_data.get('password')
        if confirm != pwd:
            raise ValidationError('密码不一致')
        return confirm

        需要注意的是,这个由model.form继承的类其方法都是从上往下进行运行的,因此我们对于每一个字段进行处理时,它是有一个先后顺序的。

admin.py

def admin_add(request):
    title = '新建用户'
    if request.method == 'GET':
        form = AdminModelForm()
        return render(request,'public_add-modify.html',{'form':form,'title':title})

    form = AdminModelForm(data=request.POST)
    if form.is_valid():
        form.save()
        return redirect('/admin/list')
    return render(request, 'public_add-modify.html', {'form': form,'title':title})
public_add-modify.html
{% extends "layout.html" %}

{% block content %}
    <div class="container">
        <div class="panel panel-info">
            <div class="panel-heading">
{#                操作名称#}
                <h3 class="panel-title">{{ title }}</h3>
            </div>

            <div class="panel-body">
                <form method="post">
                    {% csrf_token %}
                    {% for field in form %}
                        <div class="form-group">
{#                            field.label :字段名#}
                            <label for="inputEmail3" class="col-sm-2 control-label">{{ field.label }}</label>
{#                            field:input标签#}
                            {{ field }}
{#                            field.errors:错误展示#}
                            <span style="color: red">{{ field.errors.0 }}</span>
                            {# <input type="text" class="form-control" id="inputEmail3" placeholder="姓名" name="name">#}
                        </div>
                    {% endfor %}

                    <button type="submit" class="btn btn-success">提交</button>

                </form>
            </div>
        </div>
    </div>
{% endblock %}

路由的配置

    # 用户账号添加
    path('admin/add/', admin.admin_add),

 这样我们对于用户账号的添加即可完成实现。

2.3 账号信息删除

        这个很简单,在之前的博客都有详细讲过,就不再赘述了,有兴趣的朋友可能看一下下面这篇博客

Python实现员工管理系统(Django页面版 ) 一-CSDN博客

admin.py

def admin_delete(request,nid):
    models.Admin.objects.filter(id=nid).delete()
    return redirect('/admin/list')

路由配置

    # 用户账号删除
    path('admin/<int:nid>/delete/', admin.admin_delete),

2.4 账号信息编辑

        我们对于账号信息编辑需要写两种编辑方向,第一个是需要编辑用户的用户名以及其权限,第二是需要重置用户的密码。

2.41 用户名和权限的修改

        在这里我们还是需要一个由model.form继承的类,然后只对与用户名和权限这两个字段进行一个修改。

admin.py

class AdminModifyModelForm(forms.ModelForm):
    class Meta:
        model = models.Admin
        # 只选取username和role这两个字段
        fields = ['username','role']

    def __init__(self,*args,**kwargs):
        super().__init__(*args,**kwargs)
        for name,field in self.fields.items():
            field.widget.attrs = {"class":"form-control"}


def admin_modify(request,nid):
    title = '编辑用户'
    title_obj = models.Admin.objects.filter(id=nid).first()
    if request.method == 'GET':
        form = AdminModifyModelForm(instance=title_obj)
        return render(request, 'public_add-modify.html', {'form': form, 'title': title})
    form = AdminModifyModelForm(instance=title_obj,data=request.POST)
    if form.is_valid():
        form.save()
        return redirect('/admin/list')
    return render(request, 'public_add-modify.html', {'form': form, 'title': title})

路由的配置

    # 用户账号编辑
    path('admin/<int:nid>/modify/', admin.admin_modify),
 2.42 密码重置

        不知道大家有没有在生活中遇到这样的事,我们在进行找回密码的时候,对它会让我们输入一个新的密码,我们在输完之后,它就会提示我们新旧密码不能一样,这样我们是不是就找到之前的密码了。

因此对于重置密码操作我们需要重写一个新的由modelform类继承的类

class AdminRestModelForm(forms.ModelForm):
    confirm_password = forms.CharField(label='确认密码',widget=forms.PasswordInput)
    class Meta:
        model = models.Admin
        fields = ['password']
        widgets = {
            'password': forms.PasswordInput(render_value=True)
        }

    def __init__(self,*args,**kwargs):
        super().__init__(*args,**kwargs)
        for name,field in self.fields.items():
            field.widget.attrs = {"class":"form-control"}

    def clean_password(self):
        print(self.cleaned_data)
        pwd = self.cleaned_data.get('password')
        md5_pwd = md5(pwd)
        # id=self.instance.pk 当前id,不加这个字段它就会默认遍历数据库中所有数据
        exists = models.Admin.objects.filter(id=self.instance.pk,password=md5_pwd).exists()
        if exists:
            raise ValidationError('新旧密码不能一致')

        return md5_pwd

    def clean_confirm_password(self):
        confirm = md5(self.cleaned_data.get('confirm_password'))
        pwd = self.cleaned_data.get('password')
        if confirm != pwd:
            raise ValidationError('密码不一致')
        return confirm

这里需要注意的是我们在对于查找之前的密码的时候需要注意的是要筛选出当前的密码,不然数据库就会默认的遍历这个数据,然后告诉你新旧密码不能一致。

def admin_reset(request,nid):
    title_obj = models.Admin.objects.filter(id=nid).first()
    title = f'重置--《{title_obj.username}》'
    if request.method == 'GET':
        form = AdminRestModelForm()
        return render(request,'public_add-modify.html',{'form':form})
    form = AdminRestModelForm(data=request.POST,instance=title_obj)
    if form.is_valid():
        form.save()
        return redirect('/admin/list')
    return render(request,'public_add-modify.html',{'form':form})

路由配置:

    # 用户密码重置
    path('admin/<int:nid>/reset/', admin.admin_reset),

        以上我们对于用户账号的处理就完成了,希望这篇博文能对大家有所帮助,如果有什么问题的可以后台私信或者评论留言,我看到了会及时回复大家。        

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

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

相关文章

栈和队列的实现(Java篇)

文章目录 一、栈的概念二、栈的实现2.1压栈(push)2.2出栈(pop)2.3获取栈顶元素(peek)2.4判断栈是否为空(isEmpty)栈的实现测试 三、队列的概念四、队列的实现4.1入队(offer)4.2出队(poll)4.3判断队列是否为空4.4获取对头元素队列的实现测试 五、循环队列5.1入队5.2出队5.3获取队…

手把手教你Linux查找Java的安装目录并设置环境变量以及Linux下执行javac未找到命令的保姆级教学

查找Java的安装目录 输入 java -version&#xff0c;查看是否成功安装Java 输入 which java&#xff0c;查看Java的执行路径 输入 ls -lrt /usr/bin/java 输入 ls -lrt /etc/alternatives/java&#xff0c;/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.242.b08-0.el7_7.x86_64 就是J…

系列七、函数

一、函数 1.1、概述 函数 是指一段可以直接被另一段程序调用的程序或代码。 也就意味着&#xff0c;这一段程序或代码MySQL中已经为我们提供好了&#xff0c;我们要做的就是在合适的业务场景调用对应的函数完成相应的业务需求即可。 1.2、分类 按照业务分类&#xff0c;MySQL中…

centOS安装bochsXshell连接centos启动可视化界面

centOS安装bochs 参考&#xff1a;https://blog.csdn.net/muzi_since/article/details/102559187 首先安装依赖环境&#xff1a; yum install gtk2 gtk2-devel yum install libXt libXt-devel yum install libXpm libXpm-devel yum install SDL SDL-devel yum install libXr…

【LeetCode刷题-哈希表】--187.重复的DNA序列

187.重复的DNA序列 本题就是找到长度为10的字符出现次数大于2的 子串序列 方法&#xff1a;使用哈希表 class Solution {public List<String> findRepeatedDnaSequences(String s) {List<String> ans new ArrayList<String>();HashMap<String,Integer&g…

【LeetCode刷题-字符串】-- 186.反转字符串中的单词II

186.反转字符串中的单词II 方法&#xff1a;先反转整个字符串再反转单词中的字母 class Solution {public void reverseWords(char[] s) {reverseCharacters(s,0,s.length-1);reverseEachWord(s);}//反转单词中的字母public void reverseEachWord(char[] s){int length s.len…

【CASS精品教程】cass11提示“请不要在虚拟机中运行此程序”的解决办法

文章目录 一、问题提示二、解决办法一、问题提示 按照正常安装教程安装好南方测绘cass 11之后,打开的时候可能会有以下提示:请不要在虚拟机中运行此程序,如下图所示: 遇到问题,咱们就想办法解决问题,下面将自己尝试的方法及最终解决情况跟大家说一下,供参考。 二、解决…

注册与回调

C 再谈谈注册(本质是建立映射)与回调 在之前的博文中&#xff0c; 我们探讨过映射的重要作用&#xff0c; 请直接看&#xff1a;http://blog.csdn.net/stpeace/article/details/39452203, 在那篇文章中&#xff0c; 我们是用STL中的map来做的&#xff0c; map建立的是key-value…

代码随想录算法训练营Day1 | 704.二分查找、27.移除元素

LeetCode 704 二分查找 题目链接&#xff1a;704.二分查找 本题思路&#xff1a;本题题目写的是二分查找&#xff0c;所以我们用到的算法肯定也是二分查找&#xff0c;需要定义 3个变量。 l: 从数组的下标0开始 r: 数组长度 - 1 mid&#xff1a;&#xff08;l r&#xff09;…

AUTOSAR组织引入了Rust语言的原因是什么?有哪些好处?与C++相比它有什么优点?并推荐一些入门学习Rust语言链接等

AUTOSAR(汽车开放系统架构)是一个由汽车制造商、供应商和其他来自电子、半导体和软件行业的公司组成的全球发展伙伴关系,自2003年以来一直致力于为汽车行业开发和引入开放、标准化的软件平台。 AUTOSAR 最近宣布成立一个新的工作组,用于探索在汽车软件中使用 Rust 编程语言…

【网络安全】网络防护之旅 - 点燃网络安全战场的数字签名烟火

​ &#x1f308;个人主页&#xff1a;Sarapines Programmer&#x1f525; 系列专栏&#xff1a;《网络安全之道 | 数字征程》⏰墨香寄清辞&#xff1a;千里传信如电光&#xff0c;密码奥妙似仙方。 挑战黑暗剑拔弩张&#xff0c;网络战场誓守长。 ​ 目录 &#x1f608;1. 初识…

2023年总结,讲讲我的故事吧,十年

文章目录 2023前十年后十年 周末&#xff0c;本该是提升自己的最好时机&#xff0c;也该是出去玩的大好时光&#xff0c;但是毫无意外的&#xff0c;在家躺了一天&#xff0c;单纯的有点累。 2023年&#xff0c;发生了好多事情&#xff0c;又好像没发生几件事&#xff0c;可能毕…

录制第一个jmeter性能测试脚本2(http协议)_图书管理系统

我们手工编写了一个测试计划&#xff0c;现在我们通过录制的方式来实现那个测试计划。也就是说‘’测试计划目标和上一节类似&#xff1a;让5个用户在2s内登录图书管理系统&#xff0c;然后进入 页面进行查看。 目录 欢迎访问我的免费课程 PPT、安装包、视频应有尽有&#xff…

Linux Shell——输入输出重定向

输入输出重定向 1. 重定向输入2. 重定向输出 总结 最近学习了shell语法&#xff0c;总结一下关于输入输出重定向的知识。 一般情况下&#xff0c;linux每次执行命令其实都会打开三个文件&#xff0c;分别是&#xff1a; 标准输入stdin 文件描述符为0 标准输出stdout 文件描述符…

mysql8支持远程访问

上面的localhost要改为%号就打开了远程访问 ALTER USER root% IDENTIFIED WITH mysql_native_password BY fengzi2141;

NSSCTF第16页(2)

[NSSRound#4 SWPU]1zweb(revenge) 查看index.php <?php class LoveNss{public $ljt;public $dky;public $cmd;public function __construct(){$this->ljt"ljt";$this->dky"dky";phpinfo();}public function __destruct(){if($this->ljt"…

Python将列表中的数据写入csv并正确解析出来

用Python做数据处理常常会将数据写到文件中进行保存&#xff0c;又或将保存在文件中的数据读出来进行使用。通过Python将列表中的数据写入到csv文件中很多人都会&#xff0c;可以通过Python直接写文件或借助pandas很方便的实现将列表中的数据写入到csv文件中&#xff0c;但是写…

C语言—小小圣诞树

这个代码会询问用户输入圣诞树的高度&#xff0c;然后根据输入的高度在控制台上显示相应高度的圣诞树。 #include <stdio.h>int main() {int height, spaces, stars;printf("请输入圣诞树的高度: ");scanf("%d", &height);spaces height - 1;st…

【MySQL】触发器trigger / 事件

文章目录 1. 触发器 trigger1.1 触发器命名1.2 new和old关键字1.3 案例&#xff1a;insert 触发器1.4 练习&#xff1a;delete 触发器1.5 查看触发器 show triggers1.6 使用触发器记录对表的操作 2 事件2.1 打开 / 关闭事件调度器2.2 创建事件 create event2.3 查看&#xff0c…

idea__SpringBoot微服务11——整合Druid数据源(新依赖)(新注解)

整合JDBC 一、导入依赖二、配置Druid————————创作不易&#xff0c;如觉不错&#xff0c;随手点赞&#xff0c;关注&#xff0c;收藏(*&#xffe3;︶&#xffe3;)&#xff0c;谢谢~~ 接着 第10的 新注解&#xff1a; ConfigurationProperties ConfigurationPropert…