zoukankan      html  css  js  c++  java
  • 使用Django开发一个图书管理系统 05改造界面

    BOOKMS是一个公司内部的图书管理系统。

    本系列用多次迭代方法,逐步实现一个图书管理系统BOOKMS。

    本文主要介绍使用bootstrap美化前台页面和修改admin模块的添加图书模块时使用豆瓣api获取数据。

    再前一节里我们一件可以管理model(增删改查)。但是界面是在是太简陋,简陋到但凡是个正常人估计都无法接受。项目组里没有专业的前端的话,页面美化是一个痛苦的事,但是有了bootstrap的帮助之后,我们的页面也能像模像样。

    一。Bootstrap介绍

    Bootstrap是Twitter推出的一个开源的用于前端开发的工具包。它由Twitter的设计师Mark OttoJacob Thornton合作开发,是一个CSS/HTML框架。Bootstrap提供了优雅的HTML和CSS规范,它即是由动态CSS语言Less写成,与CSS框架Blueprint存在很多相似之处。Bootstrap一经推出后颇受欢迎,一直是GitHub上的热门开源项目,包括NASA的code.nasa.gov和MSNBC(微软全国广播公司)的Breaking News都使用了该项目。

    可以直接到http://twitter.github.com/bootstrap/下载使用。Bootstrap的出现造就了一大批黑硬工具条+小清新内容栏目组合的风格页面。

    二。项目改造,引入静态资源

    我们在项目里增加如下目录:

    image

    很显然,其中的css放置样式表、html放置设计好的静态页面、js放置脚本。我们把下载到的Bootstrap里的文件分别放入。

    要让静态资源起作用,我们需要修改setting.py文件(还记得这文件吧,反复改啊反复改):

    import os
    STATICFILES_DIRS = (
    os.path.dirname(__file__)+STATIC_URL,
    )

    然后再在bookms的urls.py里增加一条静态文件的路由:

    from django.contrib.staticfiles.urls import staticfiles_urlpatterns
    urlpatterns += staticfiles_urlpatterns()

    动server,就可以通过http://127.0.0.1:8000/static/xxx 直接浏览静态文件了。

    三。改造项目里的模板

    首先来改造base.html。base就是全站的基础母版(相当于asp.net的母版页)。

    <!DOCTYPE html>
    <html lang="en">
    <head>
    <meta charset="utf-8">
    <title>{% block title %} {% endblock %}</title>
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta name="description" content="">
    <meta name="author" content="">
    
    <!-- Le styles -->
    <link href="/static/css/bootstrap.css" rel="stylesheet">
    <style type="text/css">
    body {
    padding-top: 60px;
    padding-bottom: 40px;
    }
    .sidebar-nav {
    padding: 9px 0;
    }
    </style>
    <link href="../assets/css/bootstrap-responsive.css" rel="stylesheet">
    
    <!-- Le HTML5 shim, for IE6-8 support of HTML5 elements -->
    <!--[if lt IE 9]>
    <script src="</SCRIPT'">http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
    <![endif]-->
    </head>
    
    <body>
    
    <div class="navbar navbar-fixed-top">
    <div class="navbar-inner">
    <div class="container-fluid">
    <a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
    <span class="icon-bar"></span>
    <span class="icon-bar"></span>
    <span class="icon-bar"></span>
    </a>
    <a class="brand" href="#">图书管理</a>
    <div class="btn-group pull-right">
    <a class="btn dropdown-toggle" data-toggle="dropdown" href="#">
    <i class="icon-user"></i> Username
    <span class="caret"></span>
    </a>
    <ul class="dropdown-menu">
    <li><a href="#">个人资料</a></li>
    <li class="divider"></li>
    <li><a href="#">退出系统</a></li>
    </ul>
    </div>
    <div class="nav-collapse">
    <ul class="nav">
    <li class="active"><a href="#">首页</a></li>
    <li><a href="#about">图书管理</a></li>
    <li><a href="#about">关于</a></li>
    </ul>
    </div><!--/.nav-collapse -->
    </div>
    </div>
    </div>
    
    <div class="container-fluid">
    <div class="row-fluid">
    <div class="span2">
    <div class="well sidebar-nav">
    <ul class="nav nav-list">
    <li class="nav-header">图书管理</li>
    <li class="active"><a href="#">图书列表</a></li>
    <li><a href="#">我的图书</a></li>
    <li><a href="#">请求处理</a></li>
    </ul>
    </div><!--/.well -->
    </div><!--/span-->
    <div class="span10">
    {% block content %}
    
    {% endblock %}
    </div><!--/span-->
    </div><!--/row-->
    
    <hr>
    
    <footer>
    <p>&copy; Company 2012</p>
    </footer>
    
    </div><!--/.fluid-container-->
    
    <!-- Le javascript
    ================================================== -->
    <!-- Placed at the end of the document so the pages load faster -->
    <script src="/static/js/jquery.js"></script>
    <script src="/static/js/bootstrap-transition.js"></script>
    <script src="/static/js/bootstrap-alert.js"></script>
    <script src="/static/js/bootstrap-modal.js"></script>
    <script src="/static/js/bootstrap-dropdown.js"></script>
    <script src="/static/js/bootstrap-scrollspy.js"></script>
    <script src="/static/js/bootstrap-tab.js"></script>
    <script src="/static/js/bootstrap-tooltip.js"></script>
    <script src="/static/js/bootstrap-popover.js"></script>
    <script src="/static/js/bootstrap-button.js"></script>
    <script src="/static/js/bootstrap-collapse.js"></script>
    <script src="/static/js/bootstrap-carousel.js"></script>
    <script src="/static/js/bootstrap-typeahead.js"></script>
    
    </body>
    </html>

     

     

    然后是我们的list_book.html:

    {% extends "base.html" %}
    
    {% block title %} 图书列表 {% endblock %}
    
    {% block content %}
    <div class="row-fluid">
    <a class="btn btn-success" href="{% url bookapp.views.create_book %}"> <span class=" icon-plus icon-white" ></span>增加图书 </a>
    </div>
    {% for item in list_items.object_list %}
    <div class="row-fluid">
    <div class="span1">
    <img src="{{item.cover_img}}"/>
    </div>
    <div class="span11">
    <h2>{{item.title}}</h2>
    <p>{{item.summary}}</p>
    <p>
    <a class="btn btn-info" href="{% url bookapp.views.view_book item.id %}"><span class=" icon-check icon-white" ></span>详细 </a>
    <a class="btn btn-danger" href="{% url bookapp.views.edit_book item.id %}"> <span class=" icon-check icon-white" ></span>修改 </a>
    <a class="btn btn-danger" href="#"> <span class=" icon-check icon-white" ></span>归还 </a>
    </p>
    </div>
    </div>
    <hr>
    {% endfor %}
    <div class="row-fluid">
    {% if list_items.has_previous %}
    <a href="?page={{ list_items.previous_page_number }}">上一页</a>
    {% endif %}
    
    <span class="current">
    Page {{ list_items.number }} of {{ list_items.paginator.num_pages }}.
    </span>
    
    {% if list_items.has_next %}
    <a href="?page={{ list_items.next_page_number }}">下一页</a>
    {% endif %}
    
    </div>
    {% endblock %}

     

    这时候我们可以运行后去看看效果了

    http://127.0.0.1:8000/bookapp/book/list

    image

    四。改造后台admin模块,调用豆瓣api

    现在我们的管理员已经可以在后台录入图书信息了,但是字段相当的多,录入的工作量相当巨大。这里我们再偷懒一下,通过isbn到豆瓣api获取数据,尝试一下。

    文艺青年都上豆瓣,但是更文艺的青年呢,直接用豆瓣api 。

    豆瓣的API需要申请一个KEY,豆瓣也允许在不申请API Key的情况下进行API调用。不过在这种情况下,API调用被限制为每分钟请求不超过10次。使用API Key时,对访问的限制较为宽松,为每分钟40次,超过限制的话会被封禁。我们测试的就先不用apikey了。

    先看下豆瓣的api客户端:

    http://www.douban.com/service/apidoc/clients

    我们看其中的js客户端。

    <script type="text/javascript" src="http://www.douban.com/js/api.js?v=2" /><script type="text/javascript" src="http://www.douban.com/js/api-parser.js?v=1"></script>

    这2个我们都需要用到,这里我直接下载了它们放到前面引入的静态文件夹目录 /bookms/static/js里。

    关于admin模块的改造,推荐一篇文章:

    http://www.ibm.com/developerworks/cn/opensource/os-django-admin/?ca=drs-tp4608

    这里我们只需要改造添加图书这个功能的模板页面即可(输入isbn后通过js调用豆瓣api,解析返回值填入各输入框),所以我们做的改造实际上是扩展了添加图书这个模板而已。在/bookms/templates/bookapp/book下新建一个html文件change_form.html

    文件内容如下:

    {% extends "admin/change_form.html" %}
    
    {% block extrahead %}
    <script src="/static/js/jquery.js"></script>
    <script src="/static/js/douban/api.js"></script>
    <script src="/static/js/douban/api-parser.js"></script>
    <script language="javascript">
    $(document).ready(function(){
    $("#id_isbn").after("<span>输入10位或13位ISBN后回车,系统将自动获取图书信息</span>");
    $(":input").keypress(function(e) {
    var key = e.which;
    if (13 == key) {
    e.preventDefault();
    if(this.id=="id_isbn"){
    fnFromDouban();
    }
    var index = $(":input").index(this);
    var newIndex = index + 1;
    $(":input:eq(" + newIndex + ")").focus();
    }
    });
    });
    
    function fnFromDouban(){
    var reg=/^\d{10}|d{13}$/;
    if(!reg.test($("#id_isbn").val())){
    return false;
    }
    var bookid;
    DOUBAN.apikey = '你的豆瓣api key';
    DOUBAN.searchBooks({
    keyword:$("#id_isbn").get(0).value,
    callback:function(bookinfo){
    var list = DOUBAN.parseSubjects(bookinfo).entries;
    if(list==null||list.length==0){
    alert("没有这本书,检查看看isbn是否出错了呢。");
    $("#id_isbn").focus();
    }else{
    bookid=list[0].nid;
    DOUBAN.getBook({
    id:bookid,
    callback:function(re){
    var book = DOUBAN.parseSubject(re);
    $("#id_title").val(book.title ? book.title : "");
    $("#id_summary").val(book.summary ? book.summary : "--");
    $("#id_subtitle").val(book.attribute["subtitle"]? book.attribute["subtitle"] : "--" );
    $("#id_author").val(book.attribute["author"]);
    $("#id_translator").val(book.attribute["translator"]);
    $("#id_pages").val(book.attribute["pages"]);
    $("#id_price").val(book.attribute["price"]);
    $("#id_publisher").val(book.attribute["publisher"]);
    $("#id_pubdate").val(book.attribute["pubdate"]);
    $("#id_cover_img").val(book.link.image);
    $("#id_author_intro").val(book.attribute["author-intro"]);
    }
    })
    }
    }
    })
    
    return false;
    }
    
    </script>
    {% endblock %}

     

    这里我们只不过扩展了一下模板。加入了一下js。js里首先捕获了input里的回车按键,因为我这更偷懒的用了扫码枪,扫码枪默认的是扫到结果后帮你按个回车。

    在回头改造一下/bookms/bookapp/admin.py里的BookAdmin类,让admin模块里book类的显示更符合我们要求。

    class BookAdmin(admin.ModelAdmin):
    list_display = (id','isbn', 'title', 'author','translator','publisher','type',)
    list_filter = ('type','publisher',)
    search_fields = (id','title','isbn',)
    list_per_page=20

    来看看效果吧:

    image

    截图会有些出入,因为我是从运行的系统里截的~~~

  • 相关阅读:
    CentOS7 安装Docker 18.09.5
    CentOS7 安装Jenkins 2.164.2
    Python3从零开始爬取今日头条的新闻【一、开发环境搭建】
    Win10 安装Oracle11g2、配置PL/SQL Developer11环境
    IDEA 使用Mybatis效率飞起来的必备工具:MybatisCodeHelperPro 最新破解版,亲测可用!
    Navicat Premium 12 (64位)实现连接Oracle 11 (64位)
    VMware14 安装CentOS7 实现宿主机ping通虚拟机、虚拟机ping通宿主机、虚拟机能上网且能ping通百度
    Java中util.Date通过mybatis向数据库中datetime的操作!
    Java中try-catch-finally语句中return的执行顺序总结
    java中this用法总结
  • 原文地址:https://www.cnblogs.com/lt1983/p/2506439.html
Copyright © 2011-2022 走看看