本篇博客主要实现用户账号管理,这与之前的账号管理不同,之前的账号管理你可以理解为公司在外面买的一些手机号然后需要发放给员工做内部使用,而本篇博客的用户账号管理主要是为了后续的登录网页实现,那么我们开始今天的项目实现吧。
本次项目效果展示:
用户账号创建步骤:
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> </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位的十六进制数表示。它具有以下特点:
不可逆性:MD5加密是不可逆的,即无法从加密后的哈希值还原出原始消息内容。这使得MD5非常适合用于密码存储,因为即使数据库泄露,攻击者也无法直接获取用户的明文密码。
唯一性:不同的输入会产生不同的MD5哈希值,即使原文只有一个字符的变化,输出的哈希值也会大不相同。这使得MD5可以用于校验文件的完整性。
快速性: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),
以上我们对于用户账号的处理就完成了,希望这篇博文能对大家有所帮助,如果有什么问题的可以后台私信或者评论留言,我看到了会及时回复大家。