管理员管理
创建数据库表
models.py
1 2 3 4 | class Admin(models.Model): """管理员表""" username = models.CharField(verbose_name = "用户名" , max_length = 32 ) password = models.CharField(verbose_name = "密码" , max_length = 64 ) |
1 | 在数据库生成<br>Tools - >run manage.py task<br>执行命令 |
1 2 | makemigrations migrate |
数据库中插入一条数据
1 | insert into app01_admin(username, password ) values ( "coco" , "123" ); |
增加管理员菜单
修改/app01/templates/layout.html
<ul class="nav navbar-nav">
<li><a href="/admin/list/">管理员账户管理</a></li>
<li><a href="/depart/list/">部门管理</a></li>
<li><a href="/user/list/">用户管理</a></li>
<li><a href="/prettynum/list/">靓号管理</a></li>
</ul>
在views文件夹下新建admin.py,用于存放管理账户管理的视图函数
修改urls.py
1 2 3 4 5 6 7 | #导入admin from app01.views import depart, pretty, user, admin #添加url urlpatterns = [ #管理员账户管理 path( 'admin/list/' , admin.admin_list), ] |
admin.py
from django.shortcuts import render
from app01 import models
def admin_list(request):
"""管理员列表"""
queryset = models.Admin.objects.all()
context = {
'queryset' : queryset
}
return render(request, 'admin_list.html', context)
在templates文件夹创建admin_list.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | { % extends 'layout.html' % } { % block content % } <div class = "container" > <div style = "margin-bottom: 10px" class = "clearfix" > <a class = "btn btn-success" href = "#" > <span class = "glyphicon glyphicon-plus-sign" aria - hidden = "true" >< / span> 新建管理员 < / a> <div style = "float: right; width: 300px;" > <form> <div class = "input-group" > < input type = "text" name = "q" class = "form-control" placeholder = "Search for..." value = "{{ search_data }}" > <span class = "input-group-btn" > <button class = "btn btn-default" type = "submit" > <span class = "glyphicon glyphicon-search" aria - hidden = "true" >< / span> < / button> < / span> < / div><! - - / input - group - - > < / form> < / div> < / div> <div class = "panel panel-default" > <! - - Default panel contents - - > <div class = "panel-heading" > <span class = "glyphicon glyphicon-th-list" aria - hidden = "true" >< / span> 管理员列表 < / div> <! - - Table - - > <table class = "table table-bordered" > <thead> <tr> <th> ID < / th> <th>用户名< / th> <th>密码< / th> <th>操作< / th> < / tr> < / thead> <tbody> { % for obj in queryset % } <tr> <th>{{ obj. id }}< / th> <td>{{ obj.username }}< / td> <td> * * * * * * * * * * * * < / td> <td> <a class = "btn btn-primary btn-xs" href = "#" >编辑< / a> <a class = "btn btn-danger btn-xs" href = "#" >删除< / a> < / td> < / tr> { % endfor % } < / tbody> < / table> < / div> < / div> { % endblock % } |
管理员列表就可以在前端展示出来了
管理员列表添加分页
admin.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | from django.shortcuts import render from app01 import models from app01.utils.pagination import Pagination def admin_list(request): """管理员列表""" queryset = models.Admin.objects. all () page_object = Pagination(request, queryset) context = { 'queryset' : page_object.page_queryset, 'page_string' : page_object.html() } return render(request, 'admin_list.html' , context) |
admin_list.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 | { % extends 'layout.html' % } { % block content % } <div class = "container" > <div style = "margin-bottom: 10px" class = "clearfix" > <a class = "btn btn-success" href = "#" > <span class = "glyphicon glyphicon-plus-sign" aria - hidden = "true" >< / span> 新建管理员 < / a> <div style = "float: right; width: 300px;" > <form> <div class = "input-group" > < input type = "text" name = "q" class = "form-control" placeholder = "Search for..." value = "{{ search_data }}" > <span class = "input-group-btn" > <button class = "btn btn-default" type = "submit" > <span class = "glyphicon glyphicon-search" aria - hidden = "true" >< / span> < / button> < / span> < / div><! - - / input - group - - > < / form> < / div> < / div> <div class = "panel panel-default" > <! - - Default panel contents - - > <div class = "panel-heading" > <span class = "glyphicon glyphicon-th-list" aria - hidden = "true" >< / span> 管理员列表 < / div> <! - - Table - - > <table class = "table table-bordered" > <thead> <tr> <th> ID < / th> <th>用户名< / th> <th>密码< / th> <th>操作< / th> < / tr> < / thead> <tbody> { % for obj in queryset % } <tr> <th>{{ obj. id }}< / th> <td>{{ obj.username }}< / td> <td> * * * * * * * * * * * * < / td> <td> <a class = "btn btn-primary btn-xs" href = "#" >编辑< / a> <a class = "btn btn-danger btn-xs" href = "#" >删除< / a> < / td> < / tr> { % endfor % } < / tbody> < / table> < / div> <ul class = "pagination" > {{ page_string }} < / ul> < / div> { % endblock % } |
完成
添加搜索功能
admin.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | from django.shortcuts import render from app01 import models from app01.utils.pagination import Pagination def admin_list(request): """管理员列表""" #构造搜索 data_dict = {} search_data = request.GET.get( 'q' , "") if search_data: data_dict[ "username__contains" ] = search_data #根据搜索条件去数据库获取 queryset = models.Admin.objects. filter ( * * data_dict) #分页 page_object = Pagination(request, queryset) context = { 'queryset' : page_object.page_queryset, 'page_string' : page_object.html(), "search_data" : search_data, } return render(request, 'admin_list.html' , context) |
admin_list.html
新建管理员
admin_list.html
1 2 3 4 | <a class = "btn btn-success" href = "/admin/add/" > <span class = "glyphicon glyphicon-plus-sign" aria - hidden = "true" >< / span> 新建管理员 < / a> |
urls.py
1 | path( 'admin/add/' , admin.admin_add), |
修改/app01/views/admin.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | from django import forms from app01.utils.bootstrap import BootStrapModelForm class AdminModelForm(BootStrapModelForm): confirm_password = forms.CharField( label = "确认密码" , #默认生成的input框为text框,想要密码不显示需要使用passwordInput框,定义widget插件实现 widget = forms.PasswordInput ) class Meta: model = models.Admin fields = [ "username" , "password" , "confirm_password" ] widgets = { "password" : forms.PasswordInput } def admin_add(request): """添加管理员""" form = AdminModelForm() return render(request, 'change.html' , { 'form' : form, "title" : "新建管理员" }) |
按照之前的套路,我应该会新建一个名为admin_add.html的HTML文件来展示添加界面
这次我们优化一下
不管是pretty_add.html或者user_add.html,除了标题不一样,其他的都是一样的
没有必要在创建一个单独的HTML页面,我们只需要在一个公共的HTML页面中传入各自的标题即可
新建zpp01/templates/change.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | {% extends 'layout.html' %} {% block content %} < div class="container"> < div class="panel panel-default"> < div class="panel-heading"> < h3 class="panel-title">{{ title }}</ h3 > </ div > < div class="panel-body"> {# novalidate去除浏览器的错误提示 #} < form method="post" novalidate> {% csrf_token %} {% for field in form %} < div class="form-group"> < label >{{ field.label }}</ label > {{ field }} {# {{ field.errors }}错误信息是一个列表[错误1,错误2,错误3...], {{ field.errors.0 }}只取第一个错误1 #} < span style="color: red;">{{ field.errors.0 }}</ span > {# < input type="text" class="form-control" placeholder="姓名" name="user"> #} </ div > {% endfor %} < button type="submit" class="btn btn-primary">提 交</ button > </ form > </ div > </ div > </ div > {% endblock %} |
浏览器测试
新建管理员页面点击提交,将数据保存到数据库
admin.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | from django import forms from app01.utils.bootstrap import BootStrapModelForm class AdminModelForm(BootStrapModelForm): confirm_password = forms.CharField( label = "确认密码" , #默认生成的input框为text框,想要密码不显示需要使用passwordInput框,定义widget插件实现 widget = forms.PasswordInput ) class Meta: model = models.Admin fields = [ "username" , "password" , "confirm_password" ] widgets = { "password" : forms.PasswordInput } def admin_add(request): """添加管理员""" title = "新建管理员" if request.method = = "GET" : form = AdminModelForm() return render(request, 'change.html' , { 'form' : form, "title" : title}) form = AdminModelForm(data = request.POST) if form.is_valid(): form.save() return redirect( '/admin/list/' ) return render(request, 'change.html' , { 'form' : form, "title" : title}) |
存在问题:
密码跟确认密码输入不一致也能提交成功,需要添加校验,使密码、确认密码输入一致
修改app01/views/admin.py
,增加钩子函数 clean_confirm_password
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | <strong> #包的导入要按照内置包、第三方包、自己写的这种顺序导入,短的在前面</strong><br>from django import forms<br>#导入异常包 from django.core.exceptions import ValidationError from app01.utils.bootstrap import BootStrapModelForm class AdminModelForm(BootStrapModelForm): confirm_password = forms.CharField( label = "确认密码" , #默认生成的input框为text框,想要密码不显示需要使用passwordInput框,定义widget插件实现 widget = forms.PasswordInput ) class Meta: model = models.Admin fields = [ "username" , "password" , "confirm_password" ] widgets = { "password" : forms.PasswordInput } #钩子函数 def clean_confirm_password( self ): password = self .cleaned_data.get( "password" ) confirm = self .cleaned_data.get( "confirm_password" ) if confirm ! = password: raise ValidationError( "密码不一致,请重新输入。" ) #返回什么,此字段以后保存到数据库就是什么<br> <br> return confirm |
可以发现,数据校验成功了
但是还有个问题,当我们点击保存后,密码和密码确认框中的数据清空了
这样不是太友好,因此我们需要添加一个属性
1 | render_value = True |
浏览器测试,这样密码就不会清空了
现在又出现一个问题
直接将密码明文存储进数据库,很不安全
我们最好对其进行加密后,再进行保存
密码采用md5加密
新建app01/utils/encrypt.py
文件
1 2 3 4 5 6 | import hashlib from django.conf import settings def md5(data_string): obj = hashlib.md5(settings.SECRET_KEY.encode( 'utf-8' )) obj.update(data_string.encode( 'utf-8' )) return obj.hexdigest() |
修改app01/views/admin.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | from django import forms from django.core.exceptions import ValidationError from app01.utils.bootstrap import BootStrapModelForm from app01.utils.encrypt import md5 class AdminModelForm(BootStrapModelForm): confirm_password = forms.CharField( label = "确认密码" , #默认生成的input框为text框,想要密码不显示需要使用passwordInput框,定义widget插件实现 widget = forms.PasswordInput(render_value = True ) ) class Meta: model = models.Admin fields = [ "username" , "password" , "confirm_password" ] widgets = { "password" : forms.PasswordInput(render_value = True ) } # clean_字段名 def clean_password( self ): pwd = self .cleaned_data.get( "password" ) # return什么.password字段保存什么 return md5(pwd) #钩子函数 def clean_confirm_password( self ): pwd = self .cleaned_data.get( "password" ) confirm = md5( self .cleaned_data.get( "confirm_password" )) if confirm ! = pwd: raise ValidationError( "密码不一致,请重新输入。" ) #返回什么,此字段以后保存到数据库就是什么 return confirm |
看看效果吧
添加管理员编辑页面
修改app01/templates/admin_list.html
1 | < td > < a class="btn btn-primary btn-xs" href="/admin/{{ obj.id }}/edit/">编辑</ a >< br > < a class="btn btn-danger btn-xs" href="#">删除</ a >< br ></ td > |
修改myproject/myproject/urls.py
1 | path( 'admin/<int:nid>/edit/' , admin.admin_edit), |
添加一个公共的错误信息提示页面
在myprojrct/app01/templates/ 新建 error.html
error.html
1 2 3 4 5 6 7 | {% extends 'layout.html' %} {% block content %} < div class="container"> < div class="alert alert-danger" role="alert">{{ msg }}</ div > </ div > {% endblock %} |
编写视图函数
修改myproject/app01/views/admin.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | class AdminEditModelForm(BootStrapModelForm): class Meta: model = models.Admin fields = [ "username" ] def admin_edit(request,nid): """编辑管理员""" #如果数据存在返回一个对象,如果数据不存在,返回none row_object = models.Admin.objects. filter ( id = nid).first() #判断nid是否存在 if not row_object: return render(request, 'error.html' , { "msg" : "数据不存在" }) title = "编辑管理员" if request.method = = "GET" : # instance = row_object显示编辑框的默认值 form = AdminEditModelForm(instance = row_object) return render(request, 'change.html' , { "form" : form, "title" : title}) form = AdminEditModelForm(data = request.POST, instance = row_object) if form.is_valid(): form.save() return redirect( '/admin/list/' ) return render(request, 'change.html' , { "form" : form, "title" : title}) |
浏览器访问,修改coco
为coco1
点击提交
添加管理员删除
修改app01/templates/admin_list.html
1 2 3 4 | < td > < a class="btn btn-primary btn-xs" href="/admin/{{ obj.id }}/edit/">编辑</ a > < a class="btn btn-danger btn-xs" href="/admin/{{ obj.id}}/delete">删除</ a > </ td > |
修改myproject/myproject/urls.py
1 | path( 'admin/<int:nid>/delete/' , admin.admin_delete), |
修改myproject/app01/views/admin.py
1 2 3 4 | def admin_delete(request,nid): """删除管理员""" models.Admin.objects. filter ( id = nid).delete() return redirect( '/admin/list/' ) |
删除coco1
完成
管理员重置密码
修改app01/templates/admin_list.html
1 | < em id="__mceDel">< table class="table table-bordered"></ em >< em id="__mceDel"> < thead >< br > < tr >< br > < th >ID</ th >< br > < th >用户名</ th >< br > < th >密码</ th >< br > < th >重置密码</ th >< br > < th >操作</ th >< br > </ tr >< br > </ thead >< br > < tbody >< br > {% for obj in queryset %}< br > < tr >< br > < th >{{ obj.id }}</ th >< br > < td >{{ obj.username }}</ td >< br > < td >************</ td >< br > < td >< br > < a href="/admin/{{ obj.id }}/reset/">重置密码</ a >< br > </ td >< br > < td >< br > < a class="btn btn-primary btn-xs" href="/admin/{{ obj.id }}/edit/">编辑</ a >< br > < a class="btn btn-danger btn-xs" href="/admin/{{ obj.id }}/delete">删除</ a >< br > </ td >< br > </ tr >< br > {% endfor %}< br > </ tbody >< br ></ table ></ em > |
修改myproject/myproject/urls.py
1 | path( 'admin/<int:nid>/reset/' , admin.admin_reset), |
修改myproject/app01/views/admin.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | class AdminResetModelForm(BootStrapModelForm): confirm_password = forms.CharField( label = "确认密码" , #默认生成的input框为text框,想要密码不显示需要使用passwordInput框,定义widget插件实现 widget = forms.PasswordInput(render_value = True ) ) class Meta: model = models.Admin fields = [ "password" , "confirm_password" ] widgets = { "password" : forms.PasswordInput(render_value = True ) } # clean_字段名 def clean_password( self ): pwd = self .cleaned_data.get( "password" ) # return什么.password字段保存什么 return md5(pwd) #钩子函数 def clean_confirm_password( self ): pwd = self .cleaned_data.get( "password" ) confirm = md5( self .cleaned_data.get( "confirm_password" )) if confirm ! = pwd: raise ValidationError( "密码不一致,请重新输入。" ) #返回什么,此字段以后保存到数据库就是什么 return confirm def admin_reset(request,nid): """重置密码""" row_object = models.Admin.objects. filter ( id = nid).first() if not row_object: return render( '/admin/list/' ) title = "重置密码 - {}" . format (row_object.username) if request.method = = "GET" : form = AdminResetModelForm() return render(request, 'change.html' , { "form" : form, "title" : title}) form = AdminResetModelForm(data = request.POST, instance = row_object) if form.is_valid(): form.save() return redirect( '/admin/list/' ) return render(request, 'change.html' , { "form" : form, "title" : title}) |
添加功能:重置密码时不允许跟之前设置的密码一致
修改myproject/app01/views/admin.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | class AdminResetModelForm(BootStrapModelForm): confirm_password = forms.CharField( label = "确认密码" , #默认生成的input框为text框,想要密码不显示需要使用passwordInput框,定义widget插件实现 widget = forms.PasswordInput(render_value = True ) ) class Meta: model = models.Admin fields = [ "password" , "confirm_password" ] widgets = { "password" : forms.PasswordInput(render_value = True ) } # clean_字段名 def clean_password( self ): pwd = self .cleaned_data.get( "password" ) md5_pwd = md5(pwd) #去数据库校验当前密码和新重置的密码是否一致 exists = models.Admin.objects. filter ( id = self .instance.pk, password = md5_pwd).exists() if exists: raise ValidationError( "不能与以前的密码相同" ) # return什么.password字段保存什么 return md5_pwd #钩子函数 def clean_confirm_password( self ): pwd = self .cleaned_data.get( "password" ) confirm = md5( self .cleaned_data.get( "confirm_password" )) if confirm ! = pwd: raise ValidationError( "密码不一致,请重新输入。" ) #返回什么,此字段以后保存到数据库就是什么 return confirm |
完成
1 | <br><br> |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人