Django+Bootstrap-table实现管理员信息管理

Django+Bootstrap-table实现管理员信息管理,第1张

效果

主要分三个部分进行介绍
界面设计;动态渲染;数据获取

界面设计

(1)将这个界面分为上部导航栏、左侧导航栏和表格显示区域三部分;

我们期望的结果是通过点击左侧导航栏的选项,在右侧动态展示不同信息, 这里我们使用iframe来实现。

DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Managetitle>
    <link rel="stylesheet" href="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css">
    <script src="https://cdn.staticfile.org/twitter-bootstrap/5.1.1/js/bootstrap.bundle.min.js">script>
	<script src="https://cdn.staticfile.org/jquery/2.1.1/jquery.min.js">script>
	<script src="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/js/bootstrap.min.js">script>
head>
<body>
    <iframe height="50px" width="100%" id="top" src="{% url 'top' %}">iframe>
    <iframe height="600px" width="15%" id="left" src="{% url 'left' %}">iframe>
    <iframe height="600px" width="83%" id="right" name="show">iframe>
body>
html>

定义三个iframe:left、top和right,设置每个frame的高和宽,达到上面的布局,这里不再详细阐述,可以看上方代码。
(2)编写相应三个iframe对应网页
top和left主要是编写导航栏,可以直接搜索bootstrap的导航栏,选择自己喜欢的样式复制过来即可。


DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Managetitle>
    <link rel="stylesheet" href="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css">
    <script src="https://cdn.staticfile.org/twitter-bootstrap/5.1.1/js/bootstrap.bundle.min.js">script>
	<script src="https://cdn.staticfile.org/jquery/2.1.1/jquery.min.js">script>
	<script src="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/js/bootstrap.min.js">script>
head>
<body>
    <iframe height="50px" width="100%" id="top" src="{% url 'top' %}">iframe>
    <iframe height="600px" width="15%" id="left" src="{% url 'left' %}">iframe>
    <iframe height="600px" width="83%" id="right" name="show">iframe>
body>
html>

DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Toptitle>
	<link rel="stylesheet" href="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css">
    <script src="https://cdn.staticfile.org/twitter-bootstrap/5.1.1/js/bootstrap.bundle.min.js">script>
	<script src="https://cdn.staticfile.org/jquery/2.1.1/jquery.min.js">script>
	<script src="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/js/bootstrap.min.js">script>
head>
<body>
    <div class="navbar-header">
				
				<button type="button" class="navbar-toggle collapsed"
							data-toggle="collapse" data-target="#demo-navbar">
					<span class="sr-only">Toggle navigationspan>
						<span class="icon-bar">span>
						<span class="icon-bar">span>
						<span class="icon-bar">span>
				button>
				<a class="navbar-brand" href="#">管理系统a>
			div>
body>
html>

本文选用a标签设计导航栏,通过href实现点击跳转动作,{% url ‘student_manage’ %}表示跳转的路由,在urls中定义了和该路由绑定的视图函数,当然也可以写成静态HTML。target表示点击该标签后,请求路由,并将请求到的信息在target上显示,这里target=‘show’,在manage中定义了right iframe的名字是show。也就是说当点击标签后,进行跳转,将请求到的信息在right的iframe中显示。


DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Lefttitle>
    <link rel="stylesheet" href="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css">
    <script src="https://cdn.staticfile.org/twitter-bootstrap/5.1.1/js/bootstrap.bundle.min.js">script>
	<script src="https://cdn.staticfile.org/jquery/2.1.1/jquery.min.js">script>
	<script src="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/js/bootstrap.min.js">script>
head>
<body>
    <div class="list-group">
        <a href="{% url 'student_manage' %}" class="list-group-item" target="show">学生管理a>
        <a href="{% url 'book_manage' %}" class="list-group-item" target="show">图书管理a>
        <a href="{% url 'comment_manage' %}" class="list-group-item" target="show">评论管理a>
        <a href="{% url 'record_manage' %}" class="list-group-item" target="show">记录管理a>
        <a href="{% url 'advise_manage' %}" class="list-group-item" target="show">建议栏a>
    div>
body>
html>

接下来需要编写我们需要管理的各种信息界面,对应左侧导航栏中的每个选择,这里以图书管理为例,编写book_manage.html

DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <script src="https://cdn.staticfile.org/jquery/3.2.1/jquery.min.js">script>

    
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css">
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/js/bootstrap.min.js"5>script>

    
    <link rel="stylesheet" href="https://unpkg.com/bootstrap-table@1.15.3/dist/bootstrap-table.min.css">
    <script src="https://unpkg.com/bootstrap-table@1.15.3/dist/bootstrap-table.min.js">script>
    <script src="https://unpkg.com/bootstrap-table@1.15.3/dist/locale/bootstrap-table-zh-CN.min.js">script>

head>
<body>
        <div id="panel-group" >
            <div class="panel-body">
                   <div class="panel panel-primary">
            <div class="panel-heading">
                <h3 class="panel-title">图书信息管理h3>
            div>
            <div class="panel-body">
                <div style="display:inline-block;">
                    <div style="float:left;padding:6px;">
                        <span>查询内容:span>
                    div>
                    <div style="float:left;">
                        <input id="input" class="form-control" style="width:200px;" placeholder="请输入" />
                    div>
                    <div style="float:left;padding:6px;">
                        <span>查询条件:span>
                    div>
                    <div style="float:left;">
                        <select id="select" class="form-control" style="width:200px;">
                            <option value="">请选择option>
                            <option value="b_id">书号option>
                            <option value="b_isbn">ISBNoption>
                            <option value="b_pub">出版社option>
                            <option value="a_id">作者option>
                            <option value="b_category">类别option>
                            <option value="b_score">评分option>
                        select>
                    div>
                    <div style="float:left;margin-left:20px;">
                        <button id="query" class="btn btn-primary" onclick="search()">查询button>
                    div>
                    <div style="float:left;margin-left:20px;">
                        <button id="reset" class="btn btn-primary" onclick="reset()">重置button>
                    div>
                div>
            div>
        div>
                          
            <div style="width: 95%;margin-bottom: 10%;margin-right: 20px;margin-left: 20px;">
                <table id="table" >table>
            div>
		div>
body>
html>

使用boostrap-table显示各种信息,在使用时,引入bootstrap和bootstrap-table相关的js和css文件,只需要定义一个table,即

。表信息的初始化在JS代码中实现。

bootstrap-table显示信息

在JS中定义表头,请求路由,后端返回数据,在前端表中显示出来;
1、queryParams之前定义一些参数信息,重要的参数有
(1)请求路由url
(2)请求参数method,一般是get和post,默认为get
(3)pageNumber: 1 从第几页开始显示
(4)pageSize: 8 每页显示多少行
(5)sidePagination: “server”, //分页方式:client客户端分页,server服务端分页(*)
(6)queryParamsType : “limit”,设置为 ‘limit’ 则会发送符合 RESTFul 格式的参数。
2、queryParams: function (params)
在这个函数里,可以自定义参数传递到后端,比如我们设计的查询内容和查询条件,以字典的形式传递到后端进行处理
3、columns定义表头,里面主要包含三个元素
(1)field: 相当于这个字段的ID,这个要和后端传递过来的键值匹配,才能正确显示内容
(2)title: 表头显示的内容
(3)align: ‘center’, 表格对齐方式

<script type="text/javascript">
    $(function () {
        load('/info/')
    });
    function load(url){
        $('#table').bootstrapTable({
            url: url,  // 请求数据源的路由
            dataType: "json",
            method: 'post',
            pagination: true, //前端处理分页
            singleSelect: false,//是否只能单选
            search: false, //显示搜索框,此搜索是客户端搜索,不会进服务端,所以,个人感觉意义不大
            toolbar: '#toolbar', //工具按钮用哪个容器
            striped: true, //是否显示行间隔色
            cache: false, //是否使用缓存,默认为true,所以一般情况下需要设置一下这个属性(*)
            pageNumber: 1, //初始化加载第10页,默认第一页
            pageSize: 8, //每页的记录行数(*)
            pageList: [8, 20, 50, 100], //可供选择的每页的行数(*)
            strictSearch: true,//设置为 true启用 全匹配搜索,false为模糊搜索
            showColumns: false, //显示内容列下拉框
            showRefresh: false, //显示刷新按钮
            minimumCountColumns: 2, //当列数小于此值时,将隐藏内容列下拉框
            clickToSelect: true, //设置true, 将在点击某行时,自动勾选rediobox 和 checkbox
            uniqueId: "id", //每一行的唯一标识,一般为主键列
            showToggle: false, //是否显示详细视图和列表视图的切换按钮
            cardView: false, //是否显示详细视图
            sidePagination: "server", //分页方式:client客户端分页,server服务端分页(*)
            queryParamsType : "limit",//设置为 ‘limit’ 则会发送符合 RESTFul 格式的参数.
            queryParams: function (params) {//自定义参数,这里的参数是传给后台的
                    var data = {
                        size: params.limit,                             //页面大小
                        current: (params.offset / params.limit) + 1,    //页码
                        content:$('#input').val(),
                        condition:$('#select').val(),
                        table_name:'Book',
                    };
                    return data;
                },
                responseHandler: function (res) {
          //如果后台返回的json格式不是{rows:[{...},{...}],total:100},可以在这块处理成这样的格式
              return res;
            },
            columns: [{  //定义表头,这个表头必须定义,下边field后边跟的字段名字必须与后端传递的字段名字相同.如:id、name、price 跟后端的字段名id  name price是完全一样的.
                checkbox: true,
                    visible: true
				}, {
                field: 'b_id',
                title: '书号',
                align: 'center',  //对齐方式,居中
                }, {
                field: 'b_isbn',
                title: 'ISBN',
                align: 'center'
                }, {
                field: 'b_pub',
                title: '出版社',
                align: 'center'
                }, {
                field: 'b_date',
                title: '出版日期',
                align: 'center',
                }, {
                field: 'a_id',
                title: '作者',
                align: 'center',
                }, {
                field: 'b_intro',
                title: '书籍简介',
                align: 'center',
                }, {
                field: 'b_img',
                title: '封面',
                align: 'center',
                }, {
                field: 'b_score',
                title: '评分',
                align: 'center',
                }, {
                field: 'b_category',
                title: '分类',
                align: 'center',
                 }, {
                field: 'b_title',
                title: '标题',
                align: 'center',
                }, {
                field: 'op',
                title: ' *** 作',
                align: 'center',
                formatter: function (value, row, index) {
                    var result = "";
                    result += '';
                    result += '';
                    result += '';
                    result += '';
                    result += '';
                    result += '';
                    return result;
                }
            }
            ],
            });
        }
        function search(){
            $('#table').bootstrapTable('destroy');
            load('/query/');
            }
        function reset(){
            $('#table').bootstrapTable('destroy');
            $("#select").val("");
            $("#input").val("");
            load('/info/');
        }
script>

初始化时请求路由‘/info/’会查询整张表,当点击查询按钮查询数据时,需要先将表中内容清空$('#table').bootstrapTable('destroy');,然后请求查询数据路由,根据返回的数据重新渲染表格;

ORM数据库配置

首先在settings中配置数据库,本文采用的是MySQL数据库,默认使用的是sqlite3
NAME为数据库名称、USER用户名、PASSWORD密码、HOST数据库服务器地址、PORT端口号

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME':'XXX',
        'USER':'XXX',
        'PASSWORD':'XXX',
        'HOST':'XX.XX.XX.XX',
        'PORT':'3306',
    }
}
ORM表格创建

此处等待更新

ORM查询 *** 作

(1)使用filter过滤器
ob = models.Book.object.filter()返回的是Query set,可以返回多条结果;验证某个数据是否存在时,可以用ob.count()方法计算结果的数量
(2)get方法
ob = models.Book.object.get()返回的是Model,可以使用model_to_dict转化为字典进行访问,但是只能返回一个数据,如果有多条数据会报错;判断数据是否存在时,则是判断ob是否为空.

filter适合批量查询,比如查询某个作者写的所有的书籍,适合用filter。

python反射机制根据传递的表名灵活查询

反射机制:通过字符串的形式导入模块;通过字符串的形式,在模块寻找指定函数;通过字符串的形式查找某个函数中的成员

在后端管理系统中,往往有很多信息需要管理,如作者信息和书籍信息,都需要进行全表查询,将查询结果显示在前端界面。所以可以写一个视图函数,来处理全表查询 *** 作,增强代码的复用性,减少冗余性,这就需要指定表名。
在bootstrap-table里queryParams: function (params)函数中,添加参数table_name指定表名。

queryParams: function (params) {//自定义参数,这里的参数是传给后台的
    var data = {
        size: params.limit,                             //页面大小
        current: (params.offset / params.limit) + 1,    //页码
        content:$('#input').val(),
        condition:$('#select').val(),
        table_name:'Book',
    };
    return data;
},
responseHandler: function (res) {
     return res;
},

第一种反射机制:获取模块中的方法
请求方法是POST方法,参数存储在body中,先取出参数,通过getattr()获取models中的方法,第一个反射机制体现在table = getattr(models, body[‘table_name’])中。

最常用方法是models.Book.objects.all(),Book为表名,因此我们通过getattr函数,就可以获取一个table对象,直接使用table.objects.all()即可获取表的全部信息。

    if request.method == 'POST':
        body = json.loads(request.body)
        table = getattr(models, body['table_name'])
        size, current = body['size'], body['current']
        total = table.objects.count()
        infos = table.objects.all().order_by()
        #Paginator用于后端分页
        paginator = Paginator(infos, per_page=size)
        page_object = paginator.page(current)
        total = infos.count()
        rows = []
        for item in page_object:
            d = model_to_dict(item)
            for k, v in d.items():
                if 'date' in k:
                    d[k] = str(v)
                elif k == "a_id":
                    d[k] = item.a_id.a_name
            rows.append(d)
        data = {'total': total, 'rows': rows}
        return HttpResponse(json.dumps(data), content_type='application/json')

注意:bootstrap-table接收的数据类型必须为{'total':total.'rows':rows},因此需要先将数据转换成该形式,再返回给前端。此外,返回的数据必须是字符串类型,才可以显示在表格中,如果含有date类型数据,需要现将其转换为字符串。

第二种反射机制:获取某个成员中的元素
主要是先获取表格中的所有字段,再根据字段信息获取该字段对应的value值,其实本质想将model或者queryset数据转换为bootstrap可以接受的形式。但是后面发现可以直接使用model_to_dict实现,所以就舍弃了下面的方法;这种思路可以借鉴。

 body = json.loads(request.body)
table = getattr(models, body['table_name'])
fields = table._meta.fields
infos = table.objects.all()
d = {}
rows = []
for info in infos:
	for f in fields:
		d[f] = getattr(info,f)
	rows.append(d)

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/787325.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-05
下一篇 2022-05-05

发表评论

登录后才能评论

评论列表(0条)

保存