Python开发入门与实战14-基于Extjs的界面

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页面的结果如下图:

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浏览器的中文显示乱码问题。

页面运行结果如下:

14.6. 小结

本章是笔者最想写的章节,也是笔者多年开发经验的一个心得,如何通过好的架构来满足和改进项目系统的架构最后得到一个“低耦合,高内聚”的软件架构,在这个一个结构基础上我们可以不断的改进和重构我们的项目代码,为项目本身业务的进化打下坚实的基础。未来我的其它文章会继续引用这一服务来说明其它客户端的开发。

好的系统架构确实会为我们项目的长期带来收益,也可能会牺牲一点短期效率,所以整个团队的项目管理如果是建立在敏捷模式的基础上,就会在一定范围内减少对短期效率的影响。我们不用过度设计,以满足当前需求为准,最快的实现功能,并有合理的粒度的单元测试。这样,未来发现这样的代码结构不满足需要时,我们通过重构来改进代码,并通过单元测试回归来验证代码是否符合原先和现在的设计,最终让项目形成一种可以不断自我进化的机制。

本章结束python的基本的开发模式就说明完了,我们介绍在django工程里何构如建MVC模式就告一段落了,下一章开始我们讲讲项目的部署和发布。

时间: 2024-11-05 11:28:26

Python开发入门与实战14-基于Extjs的界面的相关文章

Python开发入门与实战1-开发环境

1.搭建Python Django开发环境 1.1.Python运行环境安装 Python官网:http://www.python.org/ Python最新源码,二进制文档,新闻资讯等可以在Python的官网查看到. Python3.0已经发布,本文我们使用Django作为对象映射层,Django暂时还不支持3.0版本,本文我们以Python 2.7 Windows 8 64位版本为例.下载安Windows X86-64 MSI Installer (2.7.7) [1]安装包,运行安装文件.

Python开发入门与实战8-基于Java的集成开发环境

8. 基于Java的Python的集成开发环境 目前为止我们所有的代码和例子都是通过Notepad文本编辑器来实现的,实际项目开发中这种编码模式效率较低(大虾除外),使用IDE集成开发环境常常大幅度的提高编码效率.本章我们将简要介绍两个主流的集成开发环境. 8.1. 下载安装Java运行环境 http://www.java.com/zh_CN/download/manual.jsp 根据操作系统版本下载安装Java运行时环境,如下图: 8.2.Eclipse IDE http://www.ecl

Python开发入门与实战9-基于vs的集成开发环境

9. 基于visual studio的Python的集成开发环境 上一章我们描述了如何安装使用Java的集成开发环境Eclipse IDE,本章我们来说明另一种集成开发环境,也是笔者多年的开发习惯使用的环境,也由于这个原因,接下来的章节描述都将以本章说明的集成开发环境为例. 微软的Visual Studio系列:一种在国内使用非常广泛的集成开发环境.这里我们选择的版本是community 2013版本.自从Visual Studio 也有支持Python的开发插件后,笔者很快就又重新转移到Vis

Python开发入门与实战2-第一个Django项目

2.第一个Django项目 上一章节我们完成了python,django和数据库等运行环境的安装,现在我们来创建第一个django project吧,迈出使用django开发应用的第一步. 2.1.创建第一个Django项目 我们创建一个我们存放Django的工作目录,示例:C:\My Files\Python Projects 在命令提示符窗口进入到刚才创建的目录,运行运行命令: django-admin.py startproject mysite 这样会在你的当前目录下创建一个目录mysi

Python开发入门与实战3-Django动态页面

3.Django动态页面 上一章节我们实现的helloworld视图是用来演示Django网页是创建的,它不是一个动态网页,每次运行/helloworld/,我们都将看到相同的内容,它类似一个静态HTML文件. 接下来我们将实现另一个视图,加入动态内容,例如当前日期和时间显示在网页上.通过简单的下一步,来演示Django的这个技术. 3.1.一个简单的动态页面例子 这个视图做两件事情: 获取服务器当前日期和时间,并返回包含这些值的HttpResponse .为了让Django视图显示当前日期和时

Python开发入门与实战22-简单消息回复

22. 简单消息回复 本章节我们来实现一个微信库存查询功能,使用我们前面的BIZ业务逻辑层示例如何利用微信入口来实现文本消息类的库存查询服务. 22.1. 在responseMsg函数里增加处理微信文本推送的处理逻辑 def responseMsg(postContent): postStr = smart_str(postContent) #postStr = postContent if postStr: msg = xmlContent2Dic(postStr) if msg['MsgTy

Python开发入门与实战19-Windows Azure部署2

19. 微软云部署2 上一章节我们介绍了如何实现在微软云通过虚拟机部署我们的在python django应用,本章我们来介绍如何Windows Azure上部署通过部署网站的方式来部署我们的应用,这种部署方式更方便,与vs 2013的集成度更高. 19.1. 创建Web 应用 我们登陆Windows Azure中国账户后进入到管理门户,选择“web 应用”,点击新建按钮,如下图: 创建完成后,我们选择myazure进度到应用的管理界面,如下图: 点击“浏览”按钮,浏览该网站,如果网站创建成功浏览

Python开发入门与实战10-事务

1. 事务 本章我们将通过一个例子来简要的说明“事务”,这个开发实战里经常遇到的名词.事务是如何体现在一个具体的业务和系统的实现里. 事务是通过将一组相关操作组合为一个,要么全部成功要么全部失败的单元,可以简化错误恢复并使应用程序更加可靠.事务具有4个特性:原子性.一致性.隔离性.持久性.业务事务就是完成具体业务操作后,形成的业务结果:数据库事务是数据库产品根据事务的特性实现的相关功能,数据库事务(Database Transaction) ,是指作为单个逻辑工作单元执行的一系列操作,要么完全地

Python开发入门与实战17-新浪云部署

17. 新浪云部署 上一章节我们介绍了如何在本地windows服务器部署python django的网站,本章我们简要说明一下如何把python django工程部署到云服务上. 本章章节我们描述如何在新浪云上部署python django 项目.首先,我们需要注册新浪云用户账号,新浪云用户现在需要实名认证,通过实名认证的账号创建的应用才能正常运行. 17.1. 创建应用 注册成功后登录SAE,进入我的首页,点击创建新应用,创建一个新的应用myseasite,开发语言选择Python. 17.2