一,CMDB相关概念
1,概念介绍
CMDB(配置管理数据库)存储与管理企业IT架构中设备的各种配置信息,它与所有服务支持和服务交付流程都紧密相联,支持这些流程的运转、发挥配置信息的价值,同时依赖于相关流程保证数据的准确性。
服务器集群或者分布式服务器 几十台、上百台,服务器相关数据信息,管理不方便。通过资产管理的方式,通过CMDB系统实现。
github一些开源的cmdb系统:https://github.com/search?q=cmdb
2,需求分析
本次开发的CMDB系统实现以下模块
1、用户管理模块
2、用户组管理模块
3、权限管理模块
4、资产主机模块
5、资产机房模块
6、资产用户模块
概括一下,本次学习开发的CMDB,是一个收集服务器信息,实现服务器信息可视化,给自动化运维监控提供数据统计和展示等基础服务。
3,设计实现
CMDB使用关系图示
本次开发的CMDB系统结构图示
二,创建CMDB项目
1,创建项目
①使用pycharm创建Django项目
项目名称为syscmdb
目录结构如下
创建静态资源static目录
②默认初始化配置
setting.py配置
时区及语言配置
3,数据库配置
'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'syscmdb', #你的数据库名称 数据库需要自己提前建好 'USER': 'root', #你的数据库用户名 'PASSWORD': 'root', #你的数据库密码 'HOST': '127.0.0.1', #你的数据库主机,留空默认为localhost 'PORT': '3306', #你的数据库端口 'OPTIONS': { "init_command": "SET sql_mode='STRICT_TRANS_TABLES'", } }
MySQL创建库syscmdb
CREATE DATABASE syscmdb DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;
初始化配置
③迁移数据库
D:websyscmdb>python manage.py makemigrations No changes detected D:websyscmdb>python manage.py migrate Operations to perform: Apply all migrations: admin, auth, contenttypes, sessions Running migrations: Applying contenttypes.0001_initial... OK Applying auth.0001_initial... OK Applying admin.0001_initial... OK Applying admin.0002_logentry_remove_auto_add... OK Applying contenttypes.0002_remove_content_type_name... OK Applying auth.0002_alter_permission_name_max_length... OK Applying auth.0003_alter_user_email_max_length... OK Applying auth.0004_alter_user_username_opts... OK Applying auth.0005_alter_user_last_login_null... OK Applying auth.0006_require_contenttypes_0002... OK Applying auth.0007_alter_validators_add_error_messages... OK Applying auth.0008_alter_user_username_max_length... OK Applying sessions.0001_initial... OK
注意:这是一个初始库,无需配置模型,迁移无需设置对应项目
查看MySQL对应的表
三,管理后台布局
1,后台前端模板介绍
使用INSPINIA模板,实现管理后台的前端模板页面
2,基础页面布局
①部署静态资源
②在应用下创建模板base方便之后分开管理
③定义路由
主路由
dashboard路由
④定义类视图
from django.shortcuts import render from django.views.generic import View # Create your views here. class IndexView(View): def get(self, request): return render(request, 'base.html')
⑤模板页面
可以通过模板页面,进行修改。或者直接使用修改好的模板
注意静态资源路径的修改和替换
⑥查看效果
注意:如果遇到静态资源无法加载的情况,注意查看settings.py里的静态资源目录配置是否正确。
如果css js都加载正常页面显示不正常,可以清除浏览器缓存再次刷新页面
如果出现404修改dashboard路由取消^符合 或者使用域名 http://127.0.0.1:8000/dashboardindex 即不加/访问
3,首页面实现
现在访问需要输入完整的地址例如http://127.0.0.1:8000/dashboard/index/
通过重定向实现输入127.0.0.1:8000即可跳转到首页index
①路由
RediretView重定向Url跳转
注意:需要加载模块
from django.views.generic import RedirectView
②视图
③首页模板
④查看效果
页面输入地址127.0.0.1:8000即可 默认首页自动跳转
4,高级视图类值TemplateView
TemplateView,这个类封装了View提供了更强大的功能。使用TemplateView,加载渲染页面
①使用TemplateView
实现原理
②视图传输数据到模板
之前视图可以传递一个字典传输数据到模板,高级视图类通过重新父类传输数据信息
class IndexView(TemplateView): template_name = 'index.html' def get_context_data(self, **kwargs): context = super(IndexView, self).get_context_data(**kwargs) context['body'] = '这是一个首页面,以后写统计信息' return context
③模板调用
④查看显示效果
四,登录管理
1,登录基本实现
实现完成首页面后,为了能够更加安全,就需要实现一个登录功能,只有登录之后,才能够查看管理后台。
①定义路由
from django.conf.urls import url, include from django.contrib import admin from django.views.generic import RedirectView from dashboard.views import * urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^$', RedirectView.as_view(url='/dashboard/')), url(r'^dashboard/', include('dashboard.urls')), url(r'login', LoginView.as_view()), ]
注意:本次登录页面指向的是dashboard内的视图所以需要导入视图
from dashboard.views import *
②定义视图
页面查看
③在后端接收用户传输数据
登录基础原理:前端页面输入账号密码===》后端接收信息参数===》类视图判断校验
模板页面通过ajax post请求发送数据
定义视图接收数据
class LoginView(TemplateView): template_name = 'login.html' def post(self, request): data = request.POST # 校验用户和密码 if data.get('username') == 'admin' and data.get('password') == '123456': res = {'status': 0, 'msg': '校验成功'} else: res = {'status': 1, 'msg': '用户名或者密码错误'} return JsonResponse(res)
当页面输入用户名和密码时 终端如下打印
④效验账号和密码并返回数据
注意:首页Json返回数据格式声明
from django.http import JsonResponse
login.html模板修改
完整代码如下
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>CMDB系统 | 登录</title> <link href="/static/css/bootstrap.min.css" rel="stylesheet"> <link href="/static/font-awesome/css/font-awesome.css" rel="stylesheet"> <link href="/static/css/animate.css" rel="stylesheet"> <link href="/static/css/style.css" rel="stylesheet"> <link href="/static/css/plugins/sweetalert/sweetalert.css" rel="stylesheet"> </head> <body class="gray-bg"> <div class="middle-box text-center loginscreen animated fadeInDown"> <div> <div> <h1 class="logo-name">CMDB</h1> </div> <h3>欢迎登录CMDB系统</h3> <p> </p> <p>快乐游戏,欢乐至上</p> <form class="m-t" id="login_form"> {% csrf_token %} <div class="form-group"> <input type="text" class="form-control" placeholder="用户名" name="username"> </div> <div class="form-group"> <input type="password" class="form-control" placeholder="密码" name="password"> </div> <button type="submit" class="btn btn-primary block full-width m-b">登录</button> </form> </div> </div> <!-- Mainly scripts --> <script src="/static/js/jquery-3.1.1.min.js"></script> <script src="/static/js/bootstrap.min.js"></script> <script src="/static/js/plugins/validate/jquery.validate.js"></script> <script src="/static/js/plugins/validate/messages_zh.js"></script> <script src="/static/js/plugins/sweetalert/sweetalert.min.js"></script> <script> $('#login_form').submit( function () { var str = $('#login_form').serialize(); $.post('{% url 'user_login' %}', str, function (res) { console.log(res) if (res.status == 0) { alert('登录成功') } else { alert('登录失败') } } ) }) </script> </body> </html>
页面显示验证
⑥美化提示窗口
模板引入sweetaltert js库
实现方式
实现效果
⑥js表单验证
引入js文件, jquery.validate 是基于jquery的,所有需要先引入jquery
效验代码
实现效果
完整代码
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>CMDB系统 | 登录</title> <link href="/static/css/bootstrap.min.css" rel="stylesheet"> <link href="/static/font-awesome/css/font-awesome.css" rel="stylesheet"> <link href="/static/css/animate.css" rel="stylesheet"> <link href="/static/css/style.css" rel="stylesheet"> <link href="/static/css/plugins/sweetalert/sweetalert.css" rel="stylesheet"> </head> <body class="gray-bg"> <div class="middle-box text-center loginscreen animated fadeInDown"> <div> <div> <h1 class="logo-name">CMDB</h1> </div> <h3>欢迎登录CMDB系统</h3> <p> </p> <p>快乐游戏,欢乐至上</p> <form class="m-t" id="login_form"> {% csrf_token %} <div class="form-group"> <input type="text" class="form-control" placeholder="用户名" name="username"> </div> <div class="form-group"> <input type="password" class="form-control" placeholder="密码" name="password"> </div> <button type="submit" class="btn btn-primary block full-width m-b">登录</button> </form> </div> </div> <!-- Mainly scripts --> <script src="/static/js/jquery-3.1.1.min.js"></script> <script src="/static/js/bootstrap.min.js"></script> <script src="/static/js/plugins/validate/jquery.validate.js"></script> <script src="/static/js/plugins/validate/messages_zh.js"></script> <script src="/static/js/plugins/sweetalert/sweetalert.min.js"></script> <script> $(document).ready(function () { $("#login_form").validate({ rules: { username: { required: true, minlength: 4 }, password: { required: true, minlength: 6 } }, submitHandler: function () { var str = $('#login_form').serialize(); $.post('{% url 'user_login' %}', str, function (res) { console.log(res) if ( res.status == 0) { location.href = {% url 'index' %} } else { swal({ title: res.msg, type: 'error', confirmButtonText: "知道了" }); } }); } }); }); </script> </body> </html>
登录失败跳出提示,登录成功跳转到对应的首页
2,Django用户系统实现登录
以上操作,只是实现了登录的基本校验操作,但是没有用户信息,所有实际是不能够使用。
在Django中,提供了整个一套的登录相关方法,可以直接导入调用即可。
from django.contrib.auth import login, logout, authenticate authenticate():就是用来验证用户的账号密码,如果验证成功就会返回一个User对象,如果失败就会返回None。 login():用来真正执行登录的函数,这里也会生成session存储进数据库。 logout():用来注销用户的。
①实现登录功能
视图
模板不变
②使用manage.py创建用户
最后查看登录效果 和之前是一样的 不过本次验证的用户为创建的django用户而不是在视图类写死的用户
登录成功查看session
该session存储在表django_session中
3,Url拦截器
虽然已经实现了登录系统功能,但是发现即使不通过登录系统,也可以直接通过URL访问管理后台的首页。所以,还需要在首页面上进行登录验证。登录允许访问,没有登录不允许访问。
防止通过URL直接访问 防翻墙
Django中提供了验证方法:
from django.contrib.auth.mixins import LoginRequiredMixin
①添加实现
通过session如果有session则可以登录,如果没有session则跳转登录页面
导入类
视图继承
删除数据库内已经存储的session
mysql> truncate django_session;
访问页面
修改settings.py设置
视图设置
再次访问
http://127.0.0.1:8000/dashboard/
因为没有登录没有session自动跳转到以下页面
http://127.0.0.1:8000/login/?next=/dashboard/
登录成功才能显示dashboard首页
4,注销功能
注销退出登录功能,使用Django的logout方法实现即可。
注销后,返回登录页面,需要导入类方法
from django.http import HttpResponseRedirect from django.urls import reverse
注销后通过HttpResponseRedirect跳转页面。
在跳转页面的同时,需要反向去解析URL别名,需要reverse解析方法。
注意:注销后跳转到login页面,所以注销没有模板页面
①视图
②路由
③模板
基础模板修改
页面显示
3,登录原理解析
会话机制,http每次连接默认没有上下联系状态。
cookie 存储在浏览器中的一些信息,具有风险,容易被篡改
session 存储到服务器的一些信息
退出登录的方式:
①如果在浏览器清除了cookie信息,就会退出登录
cookie里记录了session_id,没有session_id就不能够找到session,所以就被判断为未登录
②直接删除session信息,虽然cookie在,session没有了,也会判定为未登录
五,用户管理模块
1,展示用户列表
用户登录之后,继续实现用户管理模块。
首先展示用户列表信息,为了方便管理项目应用,创建新应用users,负责用户管理模块,用户组管理模块和权限管理模块的开发和管理。
①创建新应用
python manage.py startapp users
②配置允许应用
③路由
主路由
users路由
from django.conf.urls import url from django.contrib import admin from users.views import * urlpatterns = [ # url(r'^admin/', admin.site.urls), url(r'/list/', UserListView.as_view(), name='user_list'), ]
④视图
注意:需要通过视图传递查询的数据到模板页面{'data': data}
from django.shortcuts import render from django.views.generic import View from django.contrib.auth.models import User # Create your views here. class UserListView(View): def get(self, request): data = User.objects.all() return render(request, 'user_list.html', {'data': data})
模板自定义数据展示
{% extends 'base.html' %} {% block mbx %} <div class="row wrapper border-bottom white-bg page-heading"> <div class="col-sm-4"> <h2>用户展示</h2> <ol class="breadcrumb"> <li> <a hreaf="{% url 'index' %}">首页</a> </li> <li> <a href="">用户管理</a> </li> <li> <a href="">用户展示</a> </li> </ol> </div> </div> {% endblock %} {% block body %} <div class="col-lg-12"> <div class="ibox float-e-margins"> <div class="ibox-title"> <h5>用户展示 </h5> </div> <div class="ibox-content"> <table class="table table-striped"> <thead> <tr> <th class="text-center">用户名</th> <th class="text-center">邮箱</th> <th class="text-center">微信</th> <th class="text-center">中文名</th> <th class="text-center">电话</th> <th class="text-center">激活状态</th> <th class="text-center">操作</th> </tr> </thead> <tbody> {# {% for one in data %}#} {# <tr>#} {# <td class="text-center">{{ one.username }}</td>#} {# <td class="text-center">{{ one.email }}</td>#} {# <td class="text-center"></td>#} {# <td class="text-center"></td>#} {# <td class="text-center"></td>#} {# {% if one.is_active == 1 %}#} {# <td class="text-center"><i class="fa fa-circle text-navy"></i></td>#} {# {% else %}#} {# <td class="text-center"><i class="fa fa-circle text-danger"></i></td>#} {# {% endif %}#} {# <td class="text-center">#} {# <button type="button" class="btn btn-primary btn-sm">更新</button>#} {# <button type="button" class="btn btn-danger btn-sm">删除</button>#} {# </td>#} {# </tr>#} {# {% endfor %}#} <tr> <td class="text-center">admin</td> <td class="text-center">admin@qq.com</td> <td class="text-center">admin123</td> <td class="text-center">超级管理员</td> <td class="text-center">13999999999</td> <td class="text-center"><i class="fa fa-circle text-navy"></i></td> <td class="text-center"><i class="fa fa-circle text-danger"></i></td> <td class="text-center"> <button type="button" class="btn btn-primary btn-sm">更新</button> <button type="button" class="btn btn-danger btn-sm">删除</button> </td> </tr> </tbody> </table> </div> </div> </div> {% endblock %}
模板从数据库收据用户信息展示
通过循环遍历数据库用户列表进行展示
{% extends 'base.html' %} {% block mbx %} <div class="row wrapper border-bottom white-bg page-heading"> <div class="col-sm-4"> <h2>用户展示</h2> <ol class="breadcrumb"> <li> <a hreaf="{% url 'index' %}">首页</a> </li> <li> <a href="">用户管理</a> </li> <li> <a href="">用户展示</a> </li> </ol> </div> </div> {% endblock %} {% block body %} <div class="col-lg-12"> <div class="ibox float-e-margins"> <div class="ibox-title"> <h5>用户展示 </h5> </div> <div class="ibox-content"> <table class="table table-striped"> <thead> <tr> <th class="text-center">用户名</th> <th class="text-center">邮箱</th> <th class="text-center">微信</th> <th class="text-center">中文名</th> <th class="text-center">电话</th> <th class="text-center">激活状态</th> <th class="text-center">操作</th> </tr> </thead> <tbody> {% for one in data %} <tr> <td class="text-center">{{ one.username }}</td> <td class="text-center">{{ one.email }}</td> <td class="text-center"></td> <td class="text-center"></td> <td class="text-center"></td> {% if one.is_active == 1 %} <td class="text-center"><i class="fa fa-circle text-navy"></i></td> {% else %} <td class="text-center"><i class="fa fa-circle text-danger"></i></td> {% endif %} <td class="text-center"> <button type="button" class="btn btn-primary btn-sm">更新</button> <button type="button" class="btn btn-danger btn-sm">删除</button> </td> </tr> {% endfor %} {# <tr>#} {# <td class="text-center">admin</td>#} {# <td class="text-center">admin@qq.com</td>#} {# <td class="text-center">admin123</td>#} {# <td class="text-center">超级管理员</td>#} {# <td class="text-center">13999999999</td>#} {# <td class="text-center"><i class="fa fa-circle text-navy"></i></td>#} {# <td class="text-center"><i class="fa fa-circle text-danger"></i></td>#} {# <td class="text-center">#} {# <button type="button" class="btn btn-primary btn-sm">更新</button>#} {# <button type="button" class="btn btn-danger btn-sm">删除</button>#} {# </td>#} {# </tr>#} </tbody> </table> </div> </div> </div> {% endblock %}
注意:为了展示多个用户又创建一个用户devops
python manage.py createsuperuser
以下代码通过判断用户状态在页面显示用户是否处于激活状态,激活状态字段值为1 修改成其他值则会在页面显示红色
<td class="text-center"><i class="fa fa-circle text-navy"></i></td> {% else %} <td class="text-center"><i class="fa fa-circle text-danger"></i></td> {% endif %}
修改
mysql> update auth_user set is_active=0 where id=2;
页面显示
2,扩展基础用户表
Django的用户表中,提供了基本必须字段:用户名称、邮箱、密码、角色(超级管理员、普通用户)
需要添加更多的用户信息,需要使用OneToOneField字段对用户表进行拓展。
①扩展模型
加入中文名、微信、电话 备注等
导入基础用户模型
扩展模型
from django.db import models # 扩展需要导入基础User模块 from django.contrib.auth.models import User # Create your models here. class Profile(models.Model): name_cn = models.CharField(max_length=50, verbose_name='中文名称') wechat = models.CharField(max_length=50, verbose_name='中文名称') phone = models.CharField(max_length=11, verbose_name='电话') info = models.TextField(verbose_name='备注') profile = models.OneToOneField(User)
②迁移数据表
D:websyscmdb>python manage.py makemigrations users D:websyscmdb>python manage.py migrate users
查看新建的数据表
③插入数据
insert into users_profile values(null,'超级管理员','admin','18888888888','我是超级管理员',1);
④修改模板输出
页面展示效果
3,高级视图类之ListView
上面的案例中使用高级视图类TemplateView,这里再使用另外一个高级视图类ListView
使用ListView 定义模型名称 数据会自动查询 并且组合
①视图
②模板
路由保持不变 修改模板遍历object_list
页面展示效果不变
4,批量创建用户
批量创建一批用户用于测试
①路由
②视图
class TestDataView(View): def get(self, request): for i in range(0, 100): user = User() profile = Profile() user.username = '测试{}'.format(i) user.password = make_password('123456') user.mail = 'test{}@qq.com'.format(i) user.save() profile.profile_id = user.id profile.name_cn = '测试{}'.format(i) profile.wechat = '测试{}'.format(i) profile.phone = '139347398{}'.format(i) profile.info = '测试{}'.format(i) profile.save() return HttpResponse('添加测试数据')
访问web页面创建用户
MySQL查看创建了一批次测试用户
页面查看
5,分页实现
以上用户会展示在同一个页面,需要进行分页处理
①通过高级视图ListView实现
每页显示8条 页面只显示了第一页的八条
②页面显示按钮
page_obj.has_previous 判断是否有上一页 page_obj.previous_page_number 上一页的页面对象 page_obj.number 当前也数 page_obj.has_next 判断是否有下一页 page_obj.next_page_number 下一页的页面对象 paginator.num_pages 最大页数 paginator.page_range 可迭代的总页数
在模板的table表后插入以下代码
<center> <div class="btn-group"> <a type='button' class="btn btn-white" ><i class="fa fa-chevron-left"></i></a> <a class="btn btn-white" >1</a> <button class="btn btn-white active">2</button> <button class="btn btn-white">3</button> <button class="btn btn-white">4</button> <a type='button' class="btn btn-white" ><i class="fa fa-chevron-right"></i></a> </div> </center>
插入一个静态的按钮页
静态按钮暂时没有点击功能 但是页面可以通过手动输入页数来实现翻页
注意:需要代码paginate_by = 8才能实现分页 否则即使输入页数也会在一个页面显示所有用户
分页按钮保留一个即可 使用迭代来实现分页
遍历输出按钮
页面显示
显示页数
页面显示
现在点击对应数字还没有对应的Url路径 所以点击无反应
修改模板
页面查看
现在可以点击对应页面查看不同页面对应的用户了 但是当前激活点击的标签没有高亮显示
修改模板
{% if page_obj.number == page%} <a class="btn btn-white active" href="{url 'user_list'}?page={{ page }}">{{ page }}</a> {% else %} <a class="btn btn-white" href="{url 'user_list'}?page={{ page }}">{{ page }}</a> {% endif %}
页面高亮显示
现在前页后页无法点击 通过判断是否有前页或者后页激活前页后页标签
{% if page_obj.has_previous %} <a type='button' class="btn btn-white" href="{url 'user_list'}?page={{ page_obj.previous_page_number }}"><i class="fa fa-chevron-left"></i></a> {% endif %}
{% if page_obj.has_next%} <a type='button' class="btn btn-white" href="{url 'user_list'}?page={{ page_obj.next_page_number }}"><i class="fa fa-chevron-right"></i></a> {% endif %}
页面显示
page_range在底部一次性显示所有的页面,下面通过重写page_range优化页数显示
修改视图
class UserListView(ListView): template_name = 'user_list.html' model = User # 每页显示8条 paginate_by = 8 def get_context_data(self, **kwargs): context = super(UserListView, self).get_context_data(**kwargs) context['page_range'] = self.page_range(context['page_obj'], context['paginator']) print(context) return context def page_range(self, page_obj, paginator): current_page = page_obj.number start = current_page - 2 end = current_page + 3 if start < 1: start = 1 if end > paginator.num_pages: end = paginator.num_pages + 1 return range(start, end)
修改模板
页面显示
注意:一般分页在前端实现
6,添加用户
①路由
②视图
class UserAddView(TemplateView): template_name = 'user_add.html' def post(self, request): data = request.POST res = {'status': 0, 'msg': '添加成功'} try: user = User() profile = Profile() user.username = data.get('username') user.password = make_password(data.get('password')) user.mail = data.get('email') user.save() profile.profile_id = user.id profile.name_cn = data.get('name_cn') profile.wechat = data.get('wechat') profile.phone = data.get('phone') profile.info = data.get('info') profile.save() except Exception as e: print(e) res = {'status': 1, 'msg': '添加失败'} return JsonResponse(res)
③前端模板
{% extends 'base.html' %} {% block load_css %} <link href="/static/css/plugins/sweetalert/sweetalert.css" rel="stylesheet"> {% endblock %} {% block mbx %} <div class="row wrapper border-bottom white-bg page-heading"> <div class="col-sm-4"> <h2>创建用户</h2> <ol class="breadcrumb"> <li> <a href="{% url 'index' %}">首页</a> </li> <li> <a href="">用户管理</a> </li> <li> <a href="">创建用户</a> </li> </ol> </div> </div> {% endblock %} {% block body %} <div class="ibox-content"> <form id="submit_form" class="form-horizontal"> {% csrf_token %} <div class="form-group"><label class="col-sm-2 control-label">用户名</label> <div class="col-sm-6"><input type="text" class="form-control" name="username"></div> </div> <div class="hr-line-dashed"></div> <div class="form-group"><label class="col-sm-2 control-label">中文名</label> <div class="col-sm-6"><input type="text" class="form-control" name="name_cn"></div> </div> <div class="hr-line-dashed"></div> <div class="form-group"><label class="col-sm-2 control-label">密码</label> <div class="col-sm-6"><input type="password" class="form-control" name="password"></div> </div> <div class="hr-line-dashed"></div> <div class="form-group"><label class="col-sm-2 control-label">邮箱</label> <div class="col-sm-6"><input type="email" class="form-control" name="email"></div> </div> <div class="hr-line-dashed"></div> <div class="form-group"><label class="col-sm-2 control-label">微信</label> <div class="col-sm-6"><input type="text" class="form-control" name="wechat"></div> </div> <div class="hr-line-dashed"></div> <div class="form-group"><label class="col-sm-2 control-label">电话</label> <div class="col-sm-6"><input type="text" class="form-control" name="phone"></div> </div> <div class="hr-line-dashed"></div> <div class="form-group"><label class="col-sm-2 control-label">简介信息</label> <div class="col-sm-6"><input type="text" class="form-control" name="info"></div> </div> <div class="hr-line-dashed"></div> <div class="form-group"> <div class="col-sm-4 col-sm-offset-2"> <a class="btn btn-white" type="submit" href="javascript:history.back(-1)">取消</a> <button class="btn btn-primary" type="submit">保存更改</button> </div> </div> </form> </div> {% endblock %} {% block load_js %} <script src="/static/js/plugins/validate/jquery.validate.js"></script> <script src="/static/js/plugins/validate/messages_zh.js"></script> <script src="/static/js/plugins/sweetalert/sweetalert.min.js"></script> <script> $(document).ready(function () { $("#submit_form").validate({ rules: { name_cn: { required: true }, username: { required: true }, email: { required: true }, password: { required: true }, phone: { required: true, minlength:11 }, wechat: { required: true } }, submitHandler: function () { var str = $('#submit_form').serialize(); $.post('{% url 'user_add' %}', str, function (res) { if (res.status == 0) { swal({ title: res.msg, type: 'success', confirmButtonText: "确定" }, function () { window.location.href = '{% url 'user_list' %}'; }); } else { swal({ title: res.msg, type: 'error', confirmButtonText: "确定" }); } }); } }); }); </script> {% endblock %}
user_list增加一个添加用户的跳转按钮
页面查看
点击后的添加用户页面
输入信息提交
在用户列表最后一页
7,更新用户
①路由
②视图
改视图由添加用户视图修改
class UserUpdateView(View): def get(self, request): return render(request, 'user_update.html', {'user_obj': User.objects.get(id=request.GET.get('id'))}) def post(self, request): data = request.POST res = {'status': 0, 'msg': '修改成功'} try: user = User.objects.get(id=data.get('uid')) profile = Profile.objects.get(profile_id=data.get('uid')) user.username = data.get('username') user.password = make_password(data.get('password')) user.mail = data.get('email') user.save() profile.profile_id = user.id profile.name_cn = data.get('name_cn') profile.wechat = data.get('wechat') profile.phone = data.get('phone') profile.info = data.get('info') profile.save() except Exception as e: print(e) res = {'status': 1, 'msg': '修改失败'} return JsonResponse(res)
③模板
user_list模板修改跳转链接
user_update.html模板 和user_add.html模板类似
{% extends 'base.html' %} {% block load_css %} <link href="/static/css/plugins/sweetalert/sweetalert.css" rel="stylesheet"> {% endblock %} {% block body %} <h1>更新用户:{{ user_obj.username }}</h1> <div class="ibox-content"> <form id="submit_form" class="form-horizontal"> {% csrf_token %} <div class="form-group"><label class="col-sm-2 control-label">用户名</label> <div class="col-sm-6"><input type="text" class="form-control" name="username" value="{{ user_obj.username }}"></div> </div> <div class="hr-line-dashed"></div> <div class="form-group"><label class="col-sm-2 control-label">中文名</label> <div class="col-sm-6"><input type="text" class="form-control" name="name_cn" value="{{ user_obj.profile.name_cn }}"></div> </div> <div class="hr-line-dashed"></div> <div class="form-group"><label class="col-sm-2 control-label">密码</label> <div class="col-sm-6"><input type="password" class="form-control" name="password"></div> </div> <div class="hr-line-dashed"></div> <div class="form-group"><label class="col-sm-2 control-label">邮箱</label> <div class="col-sm-6"><input type="email" class="form-control" name="email" value="{{ user_obj.email }}"></div> </div> <div class="hr-line-dashed"></div> <div class="form-group"><label class="col-sm-2 control-label">微信</label> <div class="col-sm-6"><input type="text" class="form-control" name="wechat" value="{{ user_obj.profile.wechat }}"></div> </div> <div class="hr-line-dashed"></div> <div class="form-group"><label class="col-sm-2 control-label">电话</label> <div class="col-sm-6"><input type="text" class="form-control" name="phone" value="{{ user_obj.profile.phone }}"></div> </div> <div class="hr-line-dashed"></div> <div class="form-group"><label class="col-sm-2 control-label">简介</label> <div class="col-sm-6"><input type="text" class="form-control" name="info" value="{{ user_obj.profile.info }}"></div> </div> <div class="hr-line-dashed"></div> <div class="form-group"> <div class="col-sm-4 col-sm-offset-2"> <input type="hidden" value="{{ user_obj.id }}" name="uid"> <a class="btn btn-white" type="submit" href="javascript:history.back(-1)">取消</a> <button class="btn btn-primary" type="submit">保存更改</button> </div> </div> </form> </div> {% endblock %} {% block load_js %} <script src="/static/js/plugins/validate/jquery.validate.js"></script> <script src="/static/js/plugins/validate/messages_zh.js"></script> <script src="/static/js/plugins/sweetalert/sweetalert.min.js"></script> <script> $(document).ready(function () { $("#submit_form").validate({ rules: { name_cn: { required: true }, username: { required: true }, email: { required: true }, password: { required: true }, phone: { required: true }, wechat: { required: true } }, submitHandler: function () { var str = $('#submit_form').serialize(); $.post('{% url 'user_update' %}', str, function (res) { if (res.status == 0) { swal({ title: res.msg, type: 'success', confirmButtonText: "确定" }, function () { window.location.href = '{% url 'user_list' %}'; }); } else { swal({ title: res.msg, type: 'error', confirmButtonText: "确定" }); } }); } }); }); </script> {% endblock %}
页面显示
八,删除用户
①路由
②视图
class UserDeleteView(View): def get(self, request): data = request.GET res = {'status': 0, 'msg': '删除成功'} try: User.objects.get(id=data.get('id')).delete() except Exception as e: print(e) res = {'status': 1, 'msg': '删除失败'} return JsonResponse(res)
③模板
删除函数
{% block load_js %} <script src="/static/js/plugins/validate/jquery.validate.js"></script> <script src="/static/js/plugins/validate/messages_zh.js"></script> <script src="/static/js/plugins/sweetalert/sweetalert.min.js"></script> <script> function user_delete(id) { if (confirm('确认删除吗?')) { {#alert(id)#} $.get("{% url 'user_delete' %}?id=" + id,function (data) { if(data.status == 0) { swal({ title: data.msg, icon: "success", confirmButtonText: '确定', }, function () { window.location.reload() }); } else { swal("删除失败", { icon: "error", }); } }); } } </script> {% endblock %}
页面显示效果
9,禁用和启用用户
①路由
②视图
class UserStatusView(View): def get(self, request): data = request.GET # 判断当前用户是禁用还是启用 # 用户是禁用则启用 用户是启用则禁用 res = {'status': 0, 'msg': '用户状态更新成功'} # 查询用户当前状态 user = User.objects.get(id=data.get('id')) status = user.is_active # 确定用户跟新的新状态 if status == 0: newstatus = 1 else: newstatus = 0 try: user = User.objects.get(id=data.get('id')) user.is_active = newstatus user.save() except Exception as e: print(e) res = {'status': 1, 'msg': '用户状态更新失败'} return JsonResponse(res)
③模板
增加两个按钮,查询状态如果用户是启用状态则显示禁用按钮,如果用户是禁用状态则显示启用按钮
在<script>插入跟新状态函数
function user_status(id) { $.get("{% url 'user_status' %}?id=" + id,function (data) { if(data.status == 0) { swal({ title: data.msg, icon: "success", confirmButtonText: '确定', }, function () { window.location.reload() }); } else { swal({ title: data.msg, icon: "error", confirmButtonText: '确定', },function () { }); } }); }
页面显示效果