Web开发基础之CMDB系统开发之一

 

  一,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:\web\syscmdb>python manage.py makemigrations
No changes detected

D:\web\syscmdb>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直接访问  防FQ

  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 修改成其他值则会在页面显示红色

{% 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 %}

  

  修改

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:\web\syscmdb>python manage.py makemigrations users
D:\web\syscmdb>python manage.py migrate users

  查看新建的数据表

 

   ③插入数据

insert into users_profile values(null,'超级管理员','admin','18888888888','我是超级管理员',1);

   ④修改模板输出

 

   页面展示效果

 

   如果报错

__init__() missing 1 required positional argument: 'on_delete'

  则是django版本不对应需要修改model

 

 

  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 () {
                          });
                        }
                    });
            }

  页面显示效果

 

 

 

 

 

 

  

  

 

 

posted @ 2020-12-14 11:01  minseo  阅读(516)  评论(2编辑  收藏  举报