设为首页 收藏本站
查看: 998|回复: 0

[经验分享] Python开发入门与实战14-基于Extjs的界面

[复制链接]

尚未签到

发表于 2015-11-29 14:58:37 | 显示全部楼层 |阅读模式
14. 基于Extjs的界面
  上一章我们实现了一个原生的html例子,本章我们将采用Extjs实现界面的展现,来说明MVC模式下我们是怎么考虑界面与业务层的关系的。

14.1. 引用Extjs目录
  首先,我们在inventory app下增加一个static目录,拷贝Extjs发布目录到static下,本章节例子我们采用的是Extjs 4.1.1版本进行说明演示,Django项目能够访问static目录我们需要修改项目setting.py的STATIC_ROOT项的值,项目才能正确装载引用的静态文件。




# Absolute path to the directory static files should be collected to.
# Don't put anything in this directory yourself; store your static files
# in apps' "static/" subdirectories and in STATICFILES_DIRS.
# Example: "/home/media/media.lawrence.com/static/"
import os.path
STATIC_ROOT = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'static').replace('\\', '/')
14.2. 增加inventoryQueryExtjs.html模板文件
  我们仿照上一章页面结构实现Extjs查询界面模板,模板代码如下:



<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
<title></title>
<link href="../static/ExtJs/resources/css/ext-all.css" rel="stylesheet" />
<script src="../static/ExtJs/bootstrap.js"></script>
<script type="text/javascript">
Ext.onReady(function () {
//    var button1 = Ext.create('Ext.button.Button', {
//        text: 'search',
//        handler: function () {
//            myStore.load({
//                params: { q: '螺母' }
//            });
//        }
//    });

//定义Extjs端 model
            Ext.define('inventory', {
extend: 'Ext.data.Model',
fields: [
{ name: 'InventoryId', type: 'string' },
{ name: 'ItemName', type: 'string' },
{ name: 'Amount', type: 'string' },
]
});
//申明一个Store类型的变量
var myStore = Ext.create('Ext.data.Store', {
model: 'inventory',
id: 'store1',
proxy: {
type: 'ajax',
                    url: '/getInventoryByItemName/', //Store与后台的交互url
                    reader: {
type: 'json',
}
}
});
//定义查询TextField和Button
var textField1 = Ext.create('Ext.form.Panel', {
width: '100%',
renderTo: 'div0',
layout: {
type: 'hbox', // 子元素横向布局
                    padding: 5
},
items: [
{
xtype: 'textfield',
name: 'query',
id: 'query',
fieldLabel: 'Item Name:',
},
{
xtype:'button',
text: 'search',
handler: function () {
myStore.load({
params: { q: Ext.getCmp("query").getValue() }  //Store装载数据是传入查询参数
                            });
}
}
]
});
var grid = Ext.create('Ext.grid.Panel', {
title: '列表',
store: myStore,
id: 'grid1',
columns: [
{ text: 'id', dataIndex: 'InventoryId' },
{ text: 'ItemName', dataIndex: 'ItemName' },
{ text: 'Amount', dataIndex: 'Amount' }
],
width: '100%',
height: 500,
forceFit: true,
renderTo: 'div1',
});
});
</script>
</head>
<body>
<div id="div0"></div>
<div id="div1"></div>
</body>
</html>
  代码说明:Extjs页面我们首先定义了一个界面使用的model类,界面控件包括文本框、按钮、grid和store。Store里我们使用了一个重要的后台交互url: / getInventoryByItemName,这个url以json格式字符串来返回查询结果,最后,返回的结果集绑定到grid里显示,查询按钮的事件里,我们根据查询条件返回的json重新装载store,刷新grid显示。关于Extjs更多的控件和用法,请参考Extjs管网,笔者在这里更多的是说明思路。
  接下里我们在views里面增加getInventoryByItemName函数以json返回数据集,并发布到urls.py里。

14.3. 数据交互url
  我们在views.py里增加函数getInventoryByItemName,请注意实现代码里,仍然是委托调用了biz层的getInventoryByItemName,这个函数的功能与原来的inventoryQuery基本功能是一致的,只是增加了Json格式化的代码部分,同时直接返回Json字符串,而不是加载模板返回渲染的网页,代码如下:



def getInventoryByItemName(request):
error = False
inventorysJson = '[]'
if 'q' in request.GET:
q = request.GET['q']
if not q:
error = True
elif len(q) > 20:
error = True        
else:
biz = InventoryBiz()
inventorys =biz.getInventoryByItemName(q)   
inventorysJson=u'['
for inventory in inventorys:
inventorysJson = inventorysJson + u'{"InventoryId":"' + str( inventory.InventoryId) + u'","ItemName":"' +  inventory.Item.ItemName + u'","Amount":"' + str( inventory.Amount) + u'"}'
inventorysJson = inventorysJson + u']'

return HttpResponse(inventorysJson)
  代码重构的这个变化会导致系统的整个结构发生很大的变化,后面的章节我们会逐步的讲到。getInventoryByItemName url变成了一个返回Json格式查询结果的url请求,成为一个可以供各种支持json格式客户端调用的API,为我们的客户端未来支持扩展到android、iOS和windows phone等前端展现提供了架构基础。

1.4. 发布Extjs页面



Views.py

def inventoryQueryExtjs(request):
return render_to_response('inventoryQueryExtjs.html')
urls.py

url(r'^inventoryQueryExtjs/$',views.inventoryQueryExtjs),
  注意:与原生html不同,采用Extjs技术的页面发布了两个url一个专门用来渲染页面inventoryQueryExtjs,一个变成了专门的返回查询结果的url请求:getInventoryByItemName,这个结构上的变化让业务逻辑层与界面层,实现了进一步的解耦和,未来我们可以不断的衍生界面端(客户端),同时,所有客户端调用统一的后台服务。
  最后,访问inventoryQueryExtjs页面的结果如下图:
DSC0000.png

14.5. 采用流行的Bootstrap框架页面
  本小节我们延伸一下页面框架,用当下流行的页面框架Bootsstrap实现上面的库存查询界面。
  http://getbootstrap.com/ 下载Bootstrap文件;
  https://jquery.com/ 下载JQuery文件。
  两个文件解压缩后分别拷贝粘贴到工程的static目录下。
  这里为了简化数据加载,我们还采用了一个第三方的bootstrap-table作为table grid操作的控件,
  http://wenzhixin.net.cn/p/bootstrap-table/docs/?locale=zh 我们下载完整包后只拷贝bootstrap-table.css\bootstrap-table.js到static目录下:
  我们新增的inventoryQueryBootstrap.html代码如下:



<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title></title>
<link href="../static/bootstrap/css/bootstrap.min.css" rel="stylesheet" />   
<script src="../static/JQuery/jquery-2.1.4.min.js"></script>
<script src="../static/bootstrap/js/bootstrap.min.js"></script>
<script src="../static/bootstrap/table/bootstrap-table.js"></script>
</head>
<body>
<form class="form-inline" role="form">
<div class="form-group">
<label for="name">Item Name:</label>
<input type="text" class="form-control" id="ItemName"placeholder="请输入物料名称">
<button id="search"  type="button">search</button>
</div>   
</form>
<table id="inventorysTable" data-cache="false">
<thead>
<tr>
<th data-field="InventoryId">Id</th>
<th data-field="ItemName">ItemName</th>
<th data-field="Amount">Amount</th>
</tr>
</thead>
</table>
</body>
</html>
<script type="text/javascript">
//初始化用户列表设置
$('#inventorysTable').bootstrapTable(
{
striped: true,
sidePagination: "client",
url: '/getInventoryByItemName/',         
});
//查询按钮点击事件
$('#search').click(function () {
var itemName = $('#ItemName').val();
$('#inventorysTable').bootstrapTable('refresh', {
url: '/getInventoryByItemName/' + "?q="
+ encodeURIComponent(itemName),
});
});

</script>
  注:上面代码中的encodeURIComponent主要是解决IE浏览器的中文显示乱码问题。
  页面运行结果如下:
DSC0001.png

14.6. 小结
  本章是笔者最想写的章节,也是笔者多年开发经验的一个心得,如何通过好的架构来满足和改进项目系统的架构最后得到一个“低耦合,高内聚”的软件架构,在这个一个结构基础上我们可以不断的改进和重构我们的项目代码,为项目本身业务的进化打下坚实的基础。未来笔者的其它文章会继续引用这一服务来说明其它客户端的开发。
  好的系统架构确实会为我们项目的长期带来收益,也可能会牺牲一点短期效率,所以整个团队的项目管理如果是建立在敏捷模式的基础上,就会在一定范围内减少对短期效率的影响。我们不用过度设计,以满足当前需求为准,最快的实现功能,并有合理的粒度的单元测试。这样,未来发现这样的代码结构不满足需要时,我们通过重构来改进代码,并通过单元测试回归来验证代码是否符合原先和现在的设计,最终让项目形成一种可以不断进化的机制。
  本章结束python的基本的开发模式就说明完了,我们介绍在django工程里何构如建MVC模式就告一段落了,下一章开始我们讲讲项目的部署和发布。

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-145002-1-1.html 上篇帖子: Python + OpenCV2 系列:2 下篇帖子: .Net程序员之Python基础教程学习----函数和异常处理[Fifth Day]
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表