欢迎关注 『Django 网页Web开发』 系列,持续更新中
欢迎关注 『Django 网页Web开发』 系列,持续更新中
class Admin(models.Model):
""" 管理员 """
username = models.CharField(verbose_name="用户名", max_length=32)
password = models.CharField(verbose_name="密码", max_length=64)
makemigrations
migrate
<li><a href="/admin/list/">管理员管理a>li>
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="{% static 'plugins/bootstrap-3.4.1/css/bootstrap.min.css' %}">
<style>
.navbar {
border-radius: 0;
{#去掉圆角#}
}
</style>
{% block css %}{% endblock %}
</head>
<body>
<nav class="navbar navbar-default">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse"
data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="/depart/list/"> XX公司用户管理系统 </a>
</div>
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<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="/pretty/list/">靓号管理</a></li>
<li><a href="#">Link</a></li>
</ul>
<ul class="nav navbar-nav navbar-right">
<li><a href="#">登录</a></li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true"
aria-expanded="false">mzh <span class="caret"></span></a>
<ul class="dropdown-menu">
<li><a href="#">个人资料</a></li>
<li><a href="#">我的信息</a></li>
<li role="separator" class="divider"></li>
<li><a href="#">注销</a></li>
</ul>
</li>
</ul>
</div>
</div>
</nav>
<div>
{% block content %}{% endblock %}
</div>
{#导入jquery和bootstrap,注意要先导入js再导入jquery,顺序的问题#}
<script src="{% static 'js/jquery-3.6.0.min.js' %}"></script>
<script src="{% static 'plugins/bootstrap-3.4.1/js/bootstrap.min.js' %}"></script>
{% block js %}{% endblock %}
</body>
</html>
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)
print(queryset)
# 分页
page_object = Pagination(request, queryset)
context = {
'queryset': page_object.page_queryset,
'page_string': page_object.html(),
}
return render(request, 'admin_list.html', context)
复制黏贴我们的靓号表,只保留管理员名和密码字段,删掉多余字段,用户名替换为管理员名,注意把超链接的内容改成admin的。
{% extends 'layout.html' %}
{% block content %}
<div class="container">
<div style="margin-bottom: 10px" class="clearfix">
<a class="btn btn-success" href="/admin/add/">
<span class="glyphicon glyphicon-plus-sign" aria-hidden="true"></span>
新建管理员
</a>
<div style="float: right;width: 300px;">
<form method="get">
<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>
</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>
</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="/admin/{{ obj.id }}/edit/">编辑</a>
<a class="btn btn-danger btn-xs" href="/admin/{{ obj.id }}/delete/">删除</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<div class="clearfix">
<ul class="pagination">
{{ page_string }}
</ul>
</div>
</div>
{% endblock %}
注意要先导包 from app01.views import admin
path('admin/list/', admin.admin_list),
后面密码存储会使用到
from django.conf import settings
import hashlib
def md5(data_string):
obj = hashlib.md5(settings.SECRET_KEY.encode('utf-8'))
obj.update(data_string.encode('utf-8'))
return obj.hexdigest()
render_value=True
表示错误后 保留原来的密码而不是直接清空
from app01.utils.encrypt import md5
class AdminModelForm(BootStrapModelForm):
confirm_password = forms.CharField(
label="确认密码",
widget=forms.PasswordInput(render_value=True)#render_value=True 表示错误后 保留原来的密码而不是直接清空
)
class Meta:
model = models.Admin
fields = ["username", 'password', "confirm_password"]
widgets = {
"password": forms.PasswordInput(render_value=True)
}
# 得到 首次输入密码的md5
def clean_password(self):
pwd = self.cleaned_data.get("password")
return md5(pwd)
# 判断两次输入的密码是否相等,返回保存进数据库的是md5后的格式
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
class AdminEditModelForm(BootStrapModelForm):
class Meta:
model = models.Admin
fields = ['username']
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})
我们观察发现使用了moudleForm之后其实所有的添加数据页面只有title标题不同,其他内容完全相同,没有必要复制新建几个差不多的html,用一个公共的chang.html来替代所有add.html,只需要在使用时传入不同的标题名即可。
return render(request, 'change.html', {'form': form, "title": title})
{% 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">
<form method="post" novalidate>
{% csrf_token %}
{% for field in form %}
<div class="form-group">
<label>{{ field.label }}label>
{{ field }}
<span style="color: red;">{{ field.errors.0 }}span>
div>
{% endfor %}
<button type="submit" class="btn btn-primary">提 交button>
form>
div>
div>
div>
{% endblock %}
注意要先导包 from app01.views import admin
path('admin/add/', admin.admin_add),
class AdminEditModelForm(BootStrapModelForm):
class Meta:
model = models.Admin
fields = ['username']
class AdminEditModelForm(BootStrapModelForm):
class Meta:
model = models.Admin
fields = ['username']
{% extends 'layout.html' %}
{% block content %}
<div class="container">
<div style="margin-bottom: 10px" class="clearfix">
<a class="btn btn-success" href="/admin/add/">
<span class="glyphicon glyphicon-plus-sign" aria-hidden="true"></span>
新建管理员
</a>
<div style="float: right;width: 300px;">
<form method="get">
<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>
</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>
</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="/admin/{{ obj.id }}/edit/">编辑</a>
<a class="btn btn-danger btn-xs" href="/admin/{{ obj.id }}/delete/">删除</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<div class="clearfix">
<ul class="pagination">
{{ page_string }}
</ul>
</div>
</div>
{% endblock %}
{% extends 'layout.html' %}
{% block content %}
<div class="container">
<div class="alert alert-danger" role="alert">{{ msg }}div>
div>
{% endblock %}
注意要先导包 from app01.views import admin
path('admin//edit/' , admin.admin_edit),
def admin_delete(request, nid):
""" 删除管理员 """
models.Admin.objects.filter(id=nid).delete()
return redirect('/admin/list/')
不变
path('admin//delete/' , admin.admin_delete),
class AdminResetModelForm(BootStrapModelForm):
confirm_password = forms.CharField(
label="确认密码",
widget=forms.PasswordInput(render_value=True)
)
class Meta:
model = models.Admin
fields = ['password', 'confirm_password']
widgets = {
"password": forms.PasswordInput(render_value=True)
}
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 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):
""" 重置密码 """
# 对象 / None
row_object = models.Admin.objects.filter(id=nid).first()
if not row_object:
return redirect('/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})
path('admin//reset/' , admin.admin_reset),
{% extends 'layout.html' %}
{% block content %}
<div class="container">
<div style="margin-bottom: 10px" class="clearfix">
<a class="btn btn-success" href="/admin/add/">
<span class="glyphicon glyphicon-plus-sign" aria-hidden="true">span>
新建管理员
a>
<div style="float: right;width: 300px;">
<form method="get">
<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>
form>
div>
div>
<div class="panel panel-default">
<div class="panel-heading">
<span class="glyphicon glyphicon-th-list" aria-hidden="true">span>
管理员列表
div>
<table class="table table-bordered">
<thead>
<tr>
<th>IDth>
<th>管理员名th>
<th>密码th>
tr>
thead>
<tbody>
{% for obj in queryset %}
<tr>
<th>{{ obj.id }}th>
<td>{{ obj.username }}td>
<td>******td>
<td>
<a href="/admin/{{ obj.id }}/reset/">重置密码a>
td>
<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>
tr>
{% endfor %}
tbody>
table>
div>
<div class="clearfix">
<ul class="pagination">
{{ page_string }}
ul>
div>
div>
{% endblock %}
大家喜欢的话,给个,点个关注!给大家分享更多有趣好玩的Python 网页Web开发知识!
版权声明:
发现你走远了@mzh原创作品,转载必须标注原文链接
Copyright 2023 mzh
Crated:2023-3-1
欢迎关注 『Django 网页Web开发』 系列,持续更新中
欢迎关注 『Django 网页Web开发』 系列,持续更新中
『01. 安装配置Django』
『02. 创建并运行一个Django项目』
『03. 初识Django』
『04. 请求和响应,网页跳转重定向,实战简易表单模拟登陆』
『05. 数据库操作,实战用户管理』
『06. 报错:You have 26 unapplied migration(s). Your project may not work properly until you apply the migra』
『07. 模板语法』
『08. 实战项目:部门和员工管理系统(01)』
『09. 实战项目:员工编辑删除功能与靓号管理(02)』
『10. 实战项目:靓号搜索功能(03)』
『11. 实战项目:分页与页码跳转功能(04)』
『12. 实战项目:分页组件的封装 面向接口编程(05)』
『13. 实战项目:添加用户时的时间选择组件(06)』
『14. 实战项目:一些面向对象的代码结构优化(07)』
『15. 实战项目:管理员增删改查,md5密码和密码重置(08)』
『16. 实战项目:BootStrap类的进一步优化(09)』
『17. 实战项目:login业务涉及cookie、session、中间件(10)』
『18. 实战项目:登录时的验证码(11)』
『19. 实战项目:初识Ajax请求(12)』
『20. 实战项目:Ajax实战之订单管理与弹出对话框(13)』
『21. 实战项目:echart数据图表(14)』
『22. 实战项目:简单的文件上传(15)』
『23. 实战项目:Excel和form和moudleForm的文件上传(16)』
【更多内容敬请期待】