文档章节

使用Django开发一个图书管理系统 05---改造界面

luckTom
 luckTom
发布于 2014/11/13 10:08
字数 1849
阅读 3548
收藏 12
点赞 0
评论 0

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

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

本文转载自:http://www.cnblogs.com/lt1983/archive/2012/05/17/2506439.html

共有 人打赏支持
luckTom
粉丝 5
博文 18
码字总数 142
作品 0
南京
技术主管
python web应用框架--MoleSys

MoleSys 基于Mole的一个企业级web应用的架子 概述 MoleSys 是一个基础架子示例,结构清晰,没有做过渡封装,包含了python web开发可能涉及的主要模块,特别适合快速 地建立一个后台数据及报表...

Jone.x ⋅ 2013/06/06 ⋅ 0

Django 开发中的最佳实践之一

Django 开发中的最佳实践之一 本文关注 Django 开发中调试的部分。 出自 Flask 项目旗下的 Werkzeug debugger Werkzeug 这个词在德语里好像是工具的意思,这里有简要的介绍。和 Django runse...

要飞得更高 ⋅ 2013/05/01 ⋅ 0

Django的一目了然

由于Django是在一个快节奏的新闻编辑室环境下开发的,它的目的是使常见的Web开发任务,快速和容易。下面是如何编写使用Django的数据库驱动的Web应用程序的一个非正式的概述。 本文件的目的是...

Prefecter ⋅ 2014/01/04 ⋅ 0

pycharm平台下的Django教程

本文面向:有python基础,刚接触web框架的初学者。   环境:windows7   python3.5.1   pycharm专业版   Django 1.10版  pip3 一、Django简介   百度百科:开放源代码的Web应用框...

yzy121403725 ⋅ 05/17 ⋅ 0

简约而不简单的Django新手图文教程

一、Django简介   百度百科:开放源代码的Web应用框架,由Python语言编写......   重点:一个大而全的框架,啥都替你考虑好了。 1. web框架介绍   具体介绍Django之前,必须先介绍WEB...

xrzs ⋅ 2012/08/09 ⋅ 0

小司机带你学: Django+Xadmin打造在线教育平台[Python2&3通用 ](一)

大家好,我是一个学习Python一年多的小司机,去年在慕课网买了Django这门课仓促的学习完毕,时隔一年发现自己已经忘得差不多了。本次复习既是自己的学习笔记总结,也想与对Python有兴趣,对D...

天涯明月笙 ⋅ 01/10 ⋅ 0

几个 Django 第三方库/applications

Django evolution 执行 ./manage.py syncdb 的时候,django会查找新的model来创建数据库表,但当我们更新model的结构时(如增加字段),则需要手工修改对应数据表的结构。Django-evolution ...

renwofei423 ⋅ 2011/01/25 ⋅ 0

Python论坛系统--LBForum

LBForum 用django开发的论坛系统,演示地址为:http://vik.haoluobo.com/lbforum/ ,界面部分抄的 FluxBB(一个开源的PHP论坛 http://fluxbb.org/ )。 虽然Django写的论坛也不少,不过还真没什...

vicalloy ⋅ 2010/03/27 ⋅ 0

django admin应用开发(1) 之 引言

第一节 引言 1.1 准备知识 Python&Django配置 Django官方主页:www.djangoproject.com 开发IDE,个人倾向于PyCharm,在这里可以快速的学习到一些Django使用技巧。 1.2 什么是应用(APP) 要想...

Kinegratii ⋅ 2014/04/04 ⋅ 0

电子图书管理--Book Library Manager

这是一个电子图书管理的软件,仿照elibpro界面。因为最近elibpro无法再丛amazon获取书的资料,所以自己用python编写了一个。不仅能获取amazon的信息,而且能使用豆瓣的API来获得中文书的信息...

匿名 ⋅ 2010/03/03 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

PHP语言系统ZBLOG或许无法重现月光博客的闪耀历史[图]

最近在写博客,希望通过自己努力打造一个优秀的教育类主题博客,名动江湖,但是问题来了,现在写博客还有前途吗?面对强大的自媒体站点围剿,还有信心和可能型吗? 至于程序部分,我选择了P...

原创小博客 ⋅ 17分钟前 ⋅ 0

IntelliJ IDEA 2018.1新特性

工欲善其事必先利其器,如果有一款IDE可以让你更高效地专注于开发以及源码阅读,为什么不试一试? 本文转载自:netty技术内幕 3月27日,jetbrains正式发布期待已久的IntelliJ IDEA 2018.1,再...

Romane ⋅ 43分钟前 ⋅ 0

浅谈设计模式之工厂模式

工厂模式(Factory Pattern)是 Java 中最常用的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。 在工厂模式中,我们在创建对象时不会对客户端暴露创建逻...

佛系程序猿灬 ⋅ 今天 ⋅ 0

Dockerfile基础命令总结

FROM 指定使用的基础base image FROM scratch # 制作base image ,不使用任何基础imageFROM centos # 使用base imageFROM ubuntu:14.04 尽量使用官方的base image,为了安全 LABEL 描述作...

ExtreU ⋅ 昨天 ⋅ 0

存储,对比私有云和公有云的不同

导读 说起公共存储,很难不与后网络公司时代的选择性外包联系起来,但尽管如此,它还是具备着简单和固有的可用性。公共存储的名字听起来也缺乏专有性,很像是把东西直接堆放在那里而不会得到...

问题终结者 ⋅ 昨天 ⋅ 0

C++难点解析之const修饰符

C++难点解析之const修饰符 c++ 相比于其他编程语言,可能是最为难掌握,概念最为复杂的。结合自己平时的C++使用经验,这里将会列举出一些常见的难点并给出相应的解释。 const修饰符 const在c...

jackie8tao ⋅ 昨天 ⋅ 0

聊聊spring cloud netflix的HystrixCommands

序 本文主要研究一下spring cloud netflix的HystrixCommands。 maven <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-clo......

go4it ⋅ 昨天 ⋅ 0

Confluence 6 从其他备份中恢复数据

一般来说,Confluence 数据库可以从 Administration Console 或者 Confluence Setup Wizard 中进行恢复。 如果你在恢复压缩的 XML 备份的时候遇到了问题,你还是可以对整个站点进行恢复的,如...

honeymose ⋅ 昨天 ⋅ 0

myeclipse10 快速搭建spring boot开发环境(入门)

1.创建一个maven的web项目 注意上面标红的部分记得选上 2.创建的maven目录结构,有缺失的目录可以自己建立目录补充 补充后 这时候一个maven的web项目创建完成 3.配置pom.xml配置文件 <proje...

小海bug ⋅ 昨天 ⋅ 0

nginx.conf

=========================================================================== nginx.conf =========================================================================== user nobody; #......

A__17 ⋅ 昨天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部