赞
踩
django创建应用程序
本文介绍如何使用jQuery,jQuery插件和Django实现基于Web的简单电子表格。 这绝不是完整的尝试,也不是与Google Docs竞争的尝试,而只是证明了当今存在大量jQuery插件和工具的情况下创建“办公室”风格的Web应用程序是多么容易。 我在后端使用了SQLite / Python / Django堆栈,但是您可以轻松地移植到另一个框架,例如Ruby on Rails。
本文使用以下Python技术(请参阅参考资料中的链接):
注意: Python 2.5不包含simplejson,但它包含在更高的Python版本中。
如果你不想去通过让所有的jQuery的依赖关系的麻烦,随时免费下载使用的连接器的完整演示相关主题 。 在前端,您需要以下技术:
所有这些第三方库都可以为您处理大部分工作量,尤其是SlickGrid。 我之所以选择使用SlickGrid是因为它具有突出显示/选择单元格组的功能,以防我想提高单元格的数学运算和解析能力。 它还允许您在滚动时加载数据。 还可以使用其他几种出色的jQuery网格,包括Flexigrid,jQuery Grid,jqGridView和Ingrid。 此外,jQuery项目还宣布了官方jQuery Grid插件的计划。
每个电子表格包含一个工作簿,每个工作簿包含一个或多个数据表。 当输入的第一个字符是等号( =
)时,工作表中的每个单元格都应执行算术运算。 否则,输入的文本应保持原样。 数据被加载到JSON对象中,异步发送到后端,然后保存到数据库。 电子表格将处理“打开”,“新建”和“保存”操作,并且工作簿的名称显示在顶部的可编辑文本框中。
单击“ 打开”将打开一个jQuery UI窗口,该窗口显示数据库中的现有工作簿。 选择工作簿后,使用异步JavaScript和XML(Ajax)检索存储的JSON数据并将其呈现到网格中。 保存以异步方式将JSON格式的网格数据发送到后端进行存储。 “新建”操作将删除所有引用并重新加载干净的工作簿。
最后,工作簿的工作表分为不同的jQuery UI选项卡。 与其他任何电子表格一样,这些选项卡显示在底部,并通过单击底部的按钮动态添加。
您将所有CSS / JavaScript /图像放置在项目顶层的资源文件夹下。 Django应用程序将包含一个名为index.html的模板,该模板不过是一点点标记,因为您希望保持HTML语义和JavaScript代码非侵入性。 诸如网格之类的组件创建是动态完成的。 电子表格定义包含在一个名为sheetsheet.js的文件中。
首先,通过发出以下命令来创建Django项目:
django-admin startproject spreadsheet
然后,通过调用以下命令,将Cd
放入新创建的项目中以创建应用程序:
django-admin startapp spreadsheet_app
本文使用SQLite3来避免进行额外的数据库工作,但可以随意使用您喜欢的任何关系数据库系统(RDBS)。 修改settings.py文件以使用清单1中的代码。
- import os
- APPLICATION_DIR = os.path.dirname( globals()[ '__file__' ] )
-
- DATABASES = {
- 'default': {
- 'ENGINE': 'django.db.backends.sqlite3',
- 'NAME': 'db',
- 'USER': '',
- 'PASSWORD': '',
- 'HOST': '',
- 'PORT': '',
- }
- }
-
- MEDIA_ROOT = os.path.join( APPLICATION_DIR, 'resources' )
- MEDIA_URL = 'http://localhost:8000/resources/'
-
- ROOT_URLCONF = 'spreadsheet.urls'
-
- TEMPLATE_DIRS = (
- os.path.join( APPLICATION_DIR, 'templates' ),
- )
-
- INSTALLED_APPS = (
- 'django.contrib.auth',
- 'django.contrib.contenttypes',
- 'django.contrib.sessions',
- 'django.contrib.sites',
- 'django.contrib.messages',
- 'spreadsheet_app',
- )
您无需在settings.py文件中修改任何其他变量。 现在,配置URL映射。 在这种情况下,仅需要两个映射:一个用于静态服务的文件,另一个指向索引。 清单2显示了代码。
- from django.conf.urls.defaults import *
- from django.conf import settings
- import spreadsheet.spreadsheet_app.views as views
-
- urlpatterns = patterns('',
- ( r'^resources/(?P<path>.*)$',
- 'django.views.static.serve',
- { 'document_root': settings.MEDIA_ROOT } ),
- url( r'^spreadsheet_app/', views.index, name="index" ) ,
- )
在项目的顶层创建一个名为资源的目录,并在其子目录中创建名为css,js和images的子目录。 下载的依赖项(例如SlickGrid)以及应用程序的自定义JavaScript代码都存储在此处。 如果您感到懒惰,只需下载演示并复制资源目录即可。
接下来,创建您的域模型(请参见清单3)。 该模型将仅包含三个字段: workbook_name
, sheet_name
和data
。 Django对象关系映射器(ORM)自动创建一个名为id
的键字段。
- # file: spreadsheet_app/models.py
-
- from django.db import models
-
- class Workbooks(models.Model):
- workbook_name = models.CharField(max_length=30)
- sheet_name = models.CharField(max_length=30)
- data = models.TextField()
如您所知,您没有充分利用Django的全部功能。 您只希望它处理后端工作,而将繁重的工作留给jQuery前端。
最后,创建索引视图。 索引视图处理您对电子表格的创建/读取/更新操作。 在不涉及索引视图的所有细节的情况下,清单4展示了如何处理传入请求的基础。
- # file:spreadsheet_app/views.py
- from django.template.context import RequestContext
- from spreadsheet.spreadsheet_app.models import Workbooks
- import simplejson as json
- from django.http import HttpResponse
-
- def index(request):
-
- app_action = request.POST.get('app_action')
- posted_data = request.POST.get('json_data')
-
- if posted_data is not None and app_action == 'save':
- ...
-
- elif app_action == 'get_sheets':
- ...
-
- elif app_action == 'list':
- ...
导入之后,您会看到索引视图接受一个请求对象,该对象包含从客户端发送的发布数据。 您将获得两个参数: app_action
和posted_data
。 app_action
参数告诉您客户端请求的操作,例如创建新的工作簿。 posted_data
参数是从客户端发送的一张工作表的JSON数据。 不同的动作由一个简单的if
语句处理; 您可以保存工作表,获取工作簿的所有工作表,或获取数据库中工作簿的列表。
您稍后将返回索引视图以查看详细信息。 现在,在sheetsheets_app目录中添加一个名为模板的目录。 在模板子目录中,添加一个名为index.html的文件,这是项目中唯一的模板。 清单5显示了代码。
- <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
- "http://www.w3.org/TR/html4/strict.dtd">
- <html>
- <head>
- <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"i>
- <title>Overly Simple Spreadsheet</title>
- <link rel="stylesheet" href="{{MEDIA_URL}}css/smoothness/jquery-ui-1.8.5.custom.css"
- type="text/css" media="screen" charset="utf-8" />
- <link rel="stylesheet" href="{{MEDIA_URL}}css/slick.grid.css" type="text/css"
- media="screen" charset="utf-8" />
- <link rel="stylesheet" href="{{MEDIA_URL}}css/examples.css" type="text/css"
- media="screen" charset="utf-8" />
- <link rel="stylesheet" href="{{MEDIA_URL}}css/spreadsheet.css" type="text/css"
- media="screen" charset="utf-8" />
-
- <script type="text/javascript" src="{{MEDIA_URL}}js/jquery-1.4.3.min.js"></script>
- <script type="text/javascript" src="{{MEDIA_URL}}js/jquery.json.js"></script>
- <script type="text/javascript" src="{{MEDIA_URL}}js/jquery-ui-1.8.5.custom.min.js">
- </script>
- <script type="text/javascript" src="{{MEDIA_URL}}js/jquery.event.drag-2.0.min.js">
- </script>
- <script type="text/javascript" src="{{MEDIA_URL}}js/ui/jquery.ui.tabs.js"></script>
- <script type="text/javascript" src="{{MEDIA_URL}}js/slick.editors.js"></script>
- <script type="text/javascript" src="{{MEDIA_URL}}js/slick.grid.js"></script>
- <script type="text/javascript" src="{{MEDIA_URL}}js/spreadsheet.js"></script>
-
- </headi>
- <body>
- </body>
- </html>
如您所见,HTML中没有控件逻辑或样式,只是标记。 事实上,身体中甚至没有任何元素。 所有这些都是由JavaScript代码即时生成的。 这个想法是通过方法调用来添加和删除元素。
加载后,电子表格将呈现UI并加载单个选项卡。 清单6显示了render_ui
的代码。
- function render_ui(){
- insert_menu_markup();
- insert_grid_markup();
- make_grid_component();
- add_newtab_button();
- insert_open_dialog_markup();
- make_open_dialog();
- }
让我们以insert_menu_markup
开头, insert_menu_markup
每种方法的操作方式。 此方法仅添加了顶部菜单HTML代码,如清单7所示。该菜单由三个按钮(新建,打开和保存)以及用于显示和输入工作簿名称的文本字段组成。 您使用jQuery prepend
来确保添加标记时,它将作为正文中的第一个元素插入。
- // OK, it's not really a menu...yet :-)
- function insert_menu_markup(){
- $("body").prepend(
- '<input type="text" id="workbook_name" name="workbook_name" value="">');
- $("body").prepend('<input id="save" type="button" value="save"/>');
- $("body").prepend('<input id="open" type="button" value="open"/>');
- $("body").prepend('<input id="new" type="button" value="new"/>');
- }
图1显示了非常简单的菜单,它实际上只是一些按钮和一个文本框。
insert_grid_markup
方法类似于insert_menu_markup
,但是这次您使用append
方法。 jQuery UI需要<div>
的列表来生成选项卡小部件:
- function insert_grid_markup(){
- var workbook_widget = '<div id="tabs" class="tabs-bottom"><ul><li></li></ul></div>';
- $('body').append(workbook_widget);
- }
现在,通过调用方法make_grid_component
使选项卡make_grid_component
。 清单8显示了代码。
- function make_grid_component(){
- $("#tabs").tabs();
- $(".tabs-bottom .ui-tabs-nav, .tabs-bottom .ui-tabs_nav > *")
- .removeClass("ui-corner-all ui-corner-top")
- .addClass("ui-corner-bottom");
- }
您使用jQuery id
选择器获取对选项卡<div>
的引用,然后调用tabs()
方法将<div>
转换为选项卡小部件。 删除默认CSS类ui-corner-top
,然后添加ui-corner-bottom
类,以便选项卡显示在底部,如图2所示。
该组件是所有数据网格的容器。 现在,在选项卡组件下添加一个按钮,该按钮将在每次单击时动态添加一个选项卡。 您可以使用add_newtab_button
方法执行此add_newtab_button
:
- function add_newtab_button(){
- $('body').append('<input id="new_tab_button" type="button" value="+"/>');
- }
最后一个要创建的可视组件是Open窗口,您可以通过调用清单9中所示的方法insert_open_dialog_markup
来创建该窗口。与其他insert标记方法一样,该窗口创建一个包含标记信息的字符串并将其附加到正文中。
- function insert_open_dialog_markup(){
- var dlg = '<div id="dialog_form" title="Open">' +
- '<div id="dialog_form" title="Open">' +
- '<p>Select an archive.</p><form>'+
- '<select id="workbook_list" name="workbook_list">' +
- '</select></form></div>';
- $("body").append(dlg);
- }
现在,这个窗口的标记是存在的,你用增加它的功能make_open_dialog
清单10的去年方法所示方法render_ui
。 通过调用.dialog()
方法并向其传递参数autoOpen:false
,除非明确打开表单,否则该表单不会显示在网页上。 对话框窗体包含一个选择列表,其中包含加载时工作簿名称的列表。
- function make_open_dialog(){
- $('#dialog_form').dialog({
- autoOpen: false,
- modal: true,
- buttons: {
- "OK":function(){
- selected_wb = $('option:selected').attr('value');
- $(this).dialog('close');
-
- // remove grid, existing forms, and recreate
- $('body').html('');
- render_ui();
-
- // load grids and create forms with invisible inputs
- load_sheets(selected_wb);
-
- // place workbook name in text field
- $('#workbook_name').val(selected_wb);
- },
- "Cancel":function(){
- $(this).dialog('close');
- }
- }
- });
- }
您再次使用jQuery选择器来获取dialog_form
的句柄并调用dialog()
方法,该方法将html
元素转换为jQuery窗口。 “打开”窗口是模式窗口,在页面加载时不会打开。 它还包含两个按钮-确定和取消。 后者只不过是关闭窗口而已。 OK
函数在选择列表中找到所选项目并获取其值。 然后,它关闭窗口,删除主体中的所有子元素,重新渲染GUI组件,并加载工作表(或者,如果您更喜欢用术语SlickGrids )。 如前所述,由于标记的生成全部在方法中,因此添加和删除这些窗口小部件组件现在变得无关紧要。
呈现UI基础之后,您现在编写一种用于使用网格打开新选项卡的方法。 继续从上至下的方法,清单11显示了openTab
方法,这是此应用程序中的关键功能。
注意:应用程序中的每个工作表都包含一个遵循简单约定的ID:tabs_,后跟工作表中的标签号。
- function openTab(sheet_id) {
- numberOfTabs = $("#tabs").tabs("length");
- tab_name = "tabs_" + numberOfTabs;
-
- $("#tabs").tabs("add","#" + tab_name,"Sheet " + numberOfTabs, numberOfTabs);
- $("#" + tab_name).css("display","block");
- $("#tabs").tabs("select",numberOfTabs);
-
- $('#'+tab_name ).css('height','80%');
- $('#'+tab_name ).css('width','95%');
- $('#'+tab_name ).css('float','left');
- add_grid(tab_name, numberOfTabs);
-
- // add form for saving this tabs data
- if(!sheet_id){
- $('body').append(
- '<form method="post" action="?" id="'+tab_name +'_form" name="'+tab_name+'_form">'+
- '<input type="hidden" id="data'+numberOfTabs+'" name="data'+numberOfTabs+'" value="">'+
- '<input type="hidden" id="sheet_id" name="sheet_id" value="">' +
- '</form>');
- } else {
- $('body').append(
- '<form method="post" action="?" id="'+tab_name +'_form" name="'+tab_name+'_form">' +
- '<input type="hidden" id="data'+numberOfTabs +'" name="data'+numberOfTabs+'" value="">'+
- '<input type="hidden" id="sheet_id" name="sheet_id" value="'+sheet_id+'">' +
- '</form>');
- }
- }
如果您感兴趣,一种编码标记字符串的好方法是使用某种JavaScript模板,而不是将字符串串联在一起。 唯一的工作表ID被保存到隐藏的input
元素中。 您还添加了一个隐藏元素,用于保存JSON数据。 隐藏的输入遵循简单的命名约定-数据后跟制表符编号。 要注意的另一个重要点是,新添加的选项卡在添加实际的SlickGrid之前已对其CSS属性进行了修改。 如果不这样做,则网格将无法正确渲染。
openTab
方法调用add_grid
方法,该方法执行SlickGrid对象的实际实例化。 清单12显示了该应用程序的繁重工作。 创建两个JavaScript对象- workbook
和grid_references
。 Workbook
对象包含对当前workbook
对象的引用,而grid_references
包含对每个SlickGrid对象的引用。 add_grid
方法接受两个参数:网格名称和网格编号。
在列定义中,您希望使用SlickGrid示例之一中提供的TextCellEditor
作为默认值(从a到p)有16列。 在列定义之后,将参数定义提供给SlickGrid。 单元格是可编辑的,可调整大小的和可选的。 确认asyncEditorLoading
选项设置为True很重要,这可以让您在网格上实现Ajax操作。
- var workbook = {};
- var grid_references = {};
-
- function add_grid(grid_name, gridNumber){
- var grid;
- var current_cell = null;
-
- // column definitions
- var columns = [
- {id:"row", name:"#", field:"num", cssClass:"cell-selection", width:40,
- cannotTriggerInsert:true, resizable:false, unselectable:true },
- {id:"a", name:"a", field:"a", width:70, cssClass:"cell-title",
- editor:TextCellEditor},
- {id:"b", name:"b", field:"b", width:70, cssClass:"cell-title",
- editor:TextCellEditor},
- {id:"c", name:"c", field:"c", width:70, cssClass:"cell-title",
- editor:TextCellEditor},
- {id:"d", name:"d", field:"d", width:70, cssClass:"cell-title",
- editor:TextCellEditor},
- {id:"e", name:"e", field:"e", width:70, cssClass:"cell-title",
- editor:TextCellEditor},
- {id:"f", name:"f", field:"f", width:70, cssClass:"cell-title",
- editor:TextCellEditor},
- {id:"g", name:"g", field:"g", width:70, cssClass:"cell-title",
- editor:TextCellEditor},
- {id:"h", name:"h", field:"h", width:70, cssClass:"cell-title",
- editor:TextCellEditor},
- {id:"i", name:"i", field:"i", width:70, cssClass:"cell-title",
- editor:TextCellEditor},
- {id:"j", name:"j", field:"j", width:70, cssClass:"cell-title",
- editor:TextCellEditor},
- {id:"k", name:"k", field:"k", width:70, cssClass:"cell-title",
- editor:TextCellEditor},
- {id:"l", name:"l", field:"l", width:70, cssClass:"cell-title",
- editor:TextCellEditor},
- {id:"m", name:"m", field:"m", width:70, cssClass:"cell-title",
- editor:TextCellEditor},
- {id:"n", name:"n", field:"n", width:70, cssClass:"cell-title",
- editor:TextCellEditor},
- {id:"o", name:"o", field:"o", width:70, cssClass:"cell-title",
- editor:TextCellEditor},
- {id:"p", name:"p", field:"p", width:70, cssClass:"cell-title",
- editor:TextCellEditor},
- ];
-
- var options = {
- editable: true,
- autoEdit: true,
- enableAddRow: true,
- enableCellNavigation: true,
- enableCellRangeSelection : true,
- asyncEditorLoading: true,
- multiSelect: true,
- leaveSpaceForNewRows : true,
- rerenderOnResize : true
- };
-
- eval("var data" + gridNumber + " = [];");
- workbook["data" + gridNumber] = [];
- for( var i=0; i < 100 ; i++ ){
- var d = (workbook["data"+gridNumber][i] = {});
- d["num"] = i;
- d["value"] = "";
- }
-
- grid = new Slick.Grid($("#"+grid_name),workbook["data"+gridNumber], columns, options);
- ...
您使用eval
语句以某种“变态”的方式动态创建变量名。 然后使用空字符串数据加载data
变量,并创建一个SlickGrid实例。
现在,向事件添加网格attach
,如清单13所示。当onCurrentCellChanged
事件发生时,它将获取网格数据并更新单元格内容。 在单元格编辑完成之前,将调用onBeforeCellEditorDestroy
事件。 触发后,您将像以前一样获取单元格数据,但是这次,您将确定第一个字符是否为等号。 如果是这样,请使用JavaScript eval
方法评估输入的表达式。
警告:请勿在生产环境中使用此代码。 它将使您的系统容易受到各种讨厌的注入攻击。 始终清理数据。
最后,保存对网格的引用以用于其他方法。
- // file: resources/js/spreadsheet.js continued
- // Events
- grid.onCurrentCellChanged = function(){
- d = grid.getData();
- row = grid.getCurrentCell().row;
- cell = grid.getCurrentCell().cell;
- this_cell_data = d[row][grid.getColumns()[cell].field];
- };
-
- grid.onBeforeCellEditorDestroy = function(){
- d = grid.getData();
- row = grid.getCurrentCell().row;
- cell = grid.getCurrentCell().cell;
- this_cell_data = d[row][grid.getColumns()[cell].field];
-
- if(this_cell_data && this_cell_data[0] === "="){
- // evaluate JavaScript expression, don't use
- // in production!!!!
- eval("var result = " + this_cell_data.substring(1));
- d[row][grid.getColumns()[cell].field] = result;
- }
- };
- grid_references[grid_name] = grid;
- };
回到规范,您的电子表格必须创建一个新工作簿以及保存并打开现有工作簿。 让我们实现新的工作簿功能,这是三个任务中最简单的一个。 在这里,您所需要做的就是销毁UI和所有引用,然后重新绘制,如清单14所示。
- $('#new').live('click', function(){
- // delete any existing references
- workbook = {};
- grid_references = {};
-
- // remove grid, existing forms, and recreate
- $('body').html('');
-
- // recreate
- render_ui();
- openTab();
- });
“保存”功能稍微复杂一些。 您使用jQuery选择器获取具有以data
开头的name属性的每个元素,然后使用each
方法遍历结果集。 要注意的最关键的事情是,使用jquery.json
插件将网格数据编码为JSON格式,以便“通过网络”发送。 您可以使用$.post
方法异步发送数据。 传递到索引视图的参数是要执行的操作(在本例中,如清单15所示,保存),唯一的工作表ID,工作簿名称以及JSON格式的网格数据。
- $('#save').live('click',function(){
- // Do a foreach on all the grids. The ^= operator gets all
- // the inputs with a name attribute that begins with data
- $("[name^='data']").each(function(index, value){
- var data_index = "data"+index;
- var sheet_id = $('#tabs_'+index+'_form').find('#sheet_id').val();
- if(sheet_id !== ''){
- sheet_id = eval(sheet_id);
- }
-
- // convenience variable for readability
- var data2post = $.JSON.encode(workbook[data_index]);
- $("#"+data_index).val(data2post);
-
- $.post( '{% url index %}', {'app_action':'save', 'sheet_id': sheet_id,
- 'workbook_name':$('#workbook_name').val(),
- 'sheet':data_index, 'json_data':data2post});
- });
- });
回想一下,打开需要使用load_sheets
方法。 现在添加该方法(请参见清单16)。 此方法必须调用后端,以将传递给该工作簿的工作表的所有工作表请求给工作表。 然后将数据加载到相应的SlickGrid对象中。 请注意,在将数据插入对象之前,必须使用decode
方法对JSON数据进行反序列化。 然后渲染网格。
- function load_sheets(workbook_name){
- $('#workbook_list').load('{% url index %}',
- {'app_action':'get_sheets','workbook_name':workbook_name},
- function(sheets, resp, t){
- sheets = $.JSON.decode(sheets);
-
- workbook = {}; // reset
- grid_references = {};
- $.each(sheets, function(index, value){
-
- // add to workbook object
- var sheet_id = value["sheet_id"];
- openTab(sheet_id);
-
- // By calling eval, we translate value from
- // a string to a JavaScript object
- workbook[index] = eval(value["data"]);
-
- // insert data into hidden
- $("#data"+index).attr('value', workbook[index]);
- grid_references["tabs_"+index].setData(workbook[index]);
- grid_references["tabs_"+index].render();
-
- });
- });
- }
最后但并非最不重要的一点是,您实现了open
函数。 再次,进行异步调用,这次发送list
操作,然后再次反序列化以JSON发送的数据。 然后,使用数据库中所有工作簿的名称更新select
列表。 然后打开对话框。 清单17显示了代码。
- $('#open').live('click',function(){
- // load is used for doing asynchronous loading of data
- $('#workbook_list').load('{% url index %}', {'app_action':'list'},
- function(workbooks,success){
- workbooks = $.JSON.decode(workbooks);
- $.each(workbooks, function(index, value){
- $('#workbook_list').append(
- '<option value="'+ value +'">'+value +'*lt;/option>');
- });
- });
-
- $('#dialog_form').dialog('open');
- });
现在,您已经对客户端发布进行了编码,您可以完成索引视图。 清单18显示了完整的索引视图,除了导入。
要(反)序列化JSON代码,请使用simplejson模块,然后命令转储对其进行序列化以及反向加载。 对于“保存”操作,如果为单个工作表指定了ID,则会更新工作表。 否则,将创建一个新工作表。
相反,“获取工作表”操作将创建一个JSON对象,其中包含特定工作簿的所有工作表。 它使用filter()
命令检索工作簿的所有工作表( QuerySet
对象)。 这等效于select * from spreadsheet_app_workbooks
workbook_name = wb_name"
select * from spreadsheet_app_workbooks
,其中workbook_name = wb_name"
。检索到集合后,您可以将它们再次转换为JSON格式,然后将其发送回客户端。
List
还使用Django ORM,但这一次使用values()
方法。 在这里,您告诉Django,“获取workbook_name
列”。 通过在QuerySet
对象上调用distinct方法,您明确表示您不需要任何重复项。 您再次使用列表推导根据结果创建列表。 对于get_sheets
和list
,您必须为jQuery返回HttpResponse
对象,以处理您的Ajax响应。
- def index(request):
- template = 'index.html'
-
- app_action = request.POST.get('app_action')
- posted_data = request.POST.get('json_data')
-
- if posted_data is not None and app_action == 'save':
- this_sheet = request.POST.get("sheet")
- this_workbook = request.POST.get("workbook_name")
- sheet_id = request.POST.get("sheet_id")
-
- posted_data = json.dumps(posted_data)
-
- if(sheet_id):
- wb = Workbooks(id=sheet_id, workbook_name=this_workbook,
- sheet_name=this_sheet, data=posted_data)
- else:
- wb = Workbooks(workbook_name=this_workbook,
- sheet_name=this_sheet, data=posted_data)
- wb.save()
-
- elif app_action == 'get_sheets':
- wb_name = request.POST.get('workbook_name')
- sheets = Workbooks.objects.filter(workbook_name=wb_name)
-
- # use list comprehension to create python list which is like a JSON object
- sheets = [{ "sheet_id":i.id, "workbook_name": i.workbook_name.encode("utf-8"),
- "sheet_name": i.sheet_name.encode("utf-8"),
- "data": json.loads(i.data.encode("utf-8"))} for i in sheets ]
-
- # dumps -> serialize to JSON
- sheets = json.dumps(sheets)
-
- return HttpResponse( sheets, mimetype='application/javascript' )
-
- elif app_action == 'list':
- workbooks = Workbooks.objects.values('workbook_name').distinct()
-
- # use list comprehension to make a list of just the work books names
- workbooks = [ i['workbook_name'] for i in workbooks ]
-
- # encode into json format before sending to page
- workbooks = json.dumps(workbooks)
-
- # We need to return an HttpResponse object in order to complete
- # the ajax call
- return HttpResponse( workbooks, mimetype='application/javascript' )
-
- return render_to_response(template, {},
- context_instance = RequestContext( request ))
现在,您已经定义了所有JavaScript方法,可以使用两个方法调用来生成应用程序,如清单19所示。
- $(document).ready(function(){
- render_ui();
- openTab();
- });
页面加载完成后,将呈现UI,并将新的选项卡插入工作簿。
现在,您可以在命令行中运行python manage syncdb
来创建数据库,以查看其电子表格应用程序的全部(缺少)功能。 完成后,执行命令python manage.py runserver
并导航到http://localhost:8000/spreadsheet_app
。 您应该看到最终版本,如图3所示。
您可以在这个项目中添加很多东西,但是我不得不施加一些自我约束。 例如,您可以包括:
尽管此Web应用程序尚未投入生产,但它演示了如何结合多种技术。 使用不引人注目JavaScript,语义HTML,JSON对象以异步方式从服务器来回传递数据,并且-尤其值得注意的是-当有许多可用的jQuery插件时,不浪费时间,这使您的工作变得更加轻松。
翻译自: https://www.ibm.com/developerworks/web/library/wa-django/index.html
django创建应用程序
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。