非理性繁荣

使用django介绍非侵入式javascript

9月21日,2008。根据JQuery丹戈javascript

有相当多的教程希望使用Ajax丹戈.尽管如此,这仍然是一个让许多人困惑的话题。我认为最根本的问题是,有三个非常不同的小组在寻找有关使用Ajax和Django的教程:

  1. 经验丰富的Web开发人员使用了许多其他框架(并且在年轻的时候管理由乘客鸽子组成的网络),他们只需要一些低级的细节。

  2. 掌握了另一个框架(通常是RubyonRails)的Web开发人员,但需要更高层次的细节来适应姜戈做事方式和他们以前的经验之间的差异。

  3. 缺乏经验的Web开发人员从未掌握过Web框架,可能对巨蟒的掌握有限,javascript,以及在Ajax应用程序中发生的客户机-服务器交互的高级概念。

通常第一组的教程是先写的,因为它们通常只需要几个段落和一个代码片段(它们占早期采用者的大多数)。然后,随着时间的推移,针对第二组和第三组的教程出版了,通常会对两组人造成伤害(和挫折)。

本教程的目的是通过实现一个简单的笔记记录应用程序,同时接触到高级应用程序,来指导那些有点Django知识但对Ajax或Javascript不了解的人。低,以及创建Ajax Web应用程序的中级概念。

如果你走过Django教程然后您就可以开始使用非侵入式的JavaScript和Ajax了。

概述

很多人会告诉你,创建Ajax webapp的第一步是选择一个javascript库。你应该用吗JQuery,或道场,或者是蟒蛇摩奇基特?但是,哇,哇。选择一个JavaScript库实际上不是第一步。

实现Ajax webapp的第一步是在不使用Ajax的情况下实现webapp。这有点违反直觉,所以我们再说一遍:实现Ajax webapp的第一步是实现不使用Ajax的webapp。

那是什么意思?

这意味着我们将从实现整个记事本应用程序开始,而不使用任何javascript,相反,使用传统的网络互动工具:表单。

之后,我们将使用javascript来改进网站,让用户体验更加愉快。但是,从没有javascript开始,我们可以确保我们的网站对于禁用javascript或使用过时浏览器的个人正常运行。

将javascript作为附加值的概念(与价值)被调用非侵入式javascript.这是最近流行的话题,但这并不意味着它是不值得的;它是.

所以,如果第一步是在没有javascript的情况下构建站点,然后,第二步将使用jquery来整理事情。

我们将使用jquery,因为它已经成为强大的轻量级javascript库的行业领导者。即使你不特别喜欢jquery,本教程研究的概念将适用于其他JS库,所以你仍然可以带着一些价值回家。

应用程序

我们正在构建的django应用程序称为笔记,而且相当简单:它的索引页显示了一列注释,并允许创建新注释。

每个注释也将有一个详细页面,它允许查看和编辑注释的内容。

就这样。尽管如此,在使用Ajax更新应用程序方面有着惊人的空间。振作起来,会很有趣的。

notes.djapp列表视图的屏幕截图。

补充材料:git repo

通常我在编写应用程序时编写教程。我在应用程序中写了一行,然后我在教程中写了一行。它有助于通过疏忽避免错误,但是它通过……错误。我一直在努力修改我的教程写作过程,这一次我对它的态度有点不同。

我使用Git编写了这个教程来进行版本控制,并认真地提交了我所做的每一个更改(好吧,直到最后20%,当我自愿丧失理智时,这样,您就可以按照存储库修订历史记录中的更改,以小步骤查看程序的增长情况。

事实上,如果你是吉特·萨维,然后我强烈建议采用这种方法。阅读本教程以获取高级详细信息并略读代码,但是,然后坐下来与Git存储库一起检查更改。

即使你对Git不太熟悉,这其实很容易做到。只要你安装了Git,下载这个压缩的Git存储库,然后输入文件夹。

然后使用查看更改历史记录日志

威尔·拉森·麦克book:阿贾克斯·图特·威尔$Git日志

如果你一直走到最开始,然后你会看到:

提交b87ad98503285f531aadc30d2bcfa3064002c2c93作者:Will Larson金沙手机网
        
         日期:2008年9月18日星期四08:42:53-0400创建Ajax-Tut项目。
        

这是我第一次承诺。要查看修订之间的更改:

Git Diff B87AD98503285F531aadc30d2bcf306402c293d178ab382f85fcb5aa5069cc764afc1b3a4a012d

这两个哈希是第一次修订的哈希,第二次修订的哈希,它输出如下文本:

diff——git a/notes/uuu init_uuuy b/notes/uu init_uuu.py新文件模式100755索引0000000..E69DE29diff——git a/notes/models.py b/notes/models.py新文件模式100755索引0000000..71A8362- - - / dev / null+++B/注释/型号.py@@-0,0+1,3@@+从django.db导入模型++#在这里创建模型。diff--git a/notes/views.py b/notes/views.py新文件模式100755索引0000000..60F00EF- - - / dev / null+++b/注释/视图.py@@-0,0+1@@+#在此处创建视图。

您可以使用Git日志确定每个修订版的哈希值,并随着程序的增长缓慢地遍历程序。

使用这种方法有两个优点:

  1. 它不是被动的,所以你不会在读书的时候把注意力放在外面,实际上,你必须理解这些变化。

  2. 即使我忘了在教程中写一组说明,存储库已经认真记录了每一个已更改的按键,所以它是拥有所有答案的缪斯女神。

尝试一下Git存储库方法,如果有用的话告诉我。

启动笔记

现在是真正开始的时候了。

  1. 创建新的Django项目。

    django-admin.py开始项目Ajax
  2. 创建笔记应用程序。

    python manage.py startapp说明
  3. 创建少量目录。

    mkdir notes/templates/notes
  4. 打开设置.py并在顶部添加这些行:

    进口操作系统根路径=操作系统.路径.目录名_文件__

    然后更改这些值:

    数据库引擎='sqlite3'数据库名称=操作系统.路径.参加根路径'说明.sqlite'媒体根目录=操作系统.路径.参加根路径'媒体'媒体URL='http://127.0.0.1:8000/media/'模板目录=操作系统.路径.参加根路径'模板'已安装的应用程序='django.contrib.auth''django.contrib.contenttypes''django.contrib.sessions''django.contrib.sites''备注'

    这些变化可能有点令人困惑,但在创建开发项目方面有着难以置信的帮助。这些设置允许项目检测其当前位置,然后为其sqlite数据库创建正确的路径,媒体目录,和模板目录。

    如果没有这些设置,你就必须自己输入绝对路径,但有了它们,您可以更改项目的目录——甚至可以将其压缩并发送给同事——这样就可以正常工作了。

    我几乎在每个开发项目中都使用它们。

  5. 接下来我们需要编辑Ajax图特/urls.py使用django媒体服务器(仅用于开发目的,不要将其用于部署!),并将所有传入的URL传递给Ajax图/notes/urls.py文件(我们还没有写)。

    Ajax图特/urls.py应该如下所示:

    django.conf.urls.defaults进口*django.conf.会议进口设置URL模式=模式r'^media/(?磷
               
                * * $
               'django.views.static.serve'{'文档\u根'设置.媒体根目录}R′包括'ajax.tut.notes.urls'

    请注意,URL是按顺序匹配的,所以即使第二个regex将匹配任何传入的URL,传入的URL将在到达前与第一个URL匹配。

    这个r'^media/(?磷 * * $ Regex允许我们使用开发服务器为静态媒体提供服务,和r'^'`简单地表示将任何到达它的URL传递给 网址.py文件 笔记应用程序。

  6. 现在是运行开发服务器并检查系统中是否有输入错误的时候了。

    python manage.py运行服务器

    然后导航到网址:http://127.0.0.1:8000你应该得到一个闪亮的错误页面,抱怨ajax tut.notes.urls(网址)模块不存在。

    我们走对了。

  7. 接下来我们要创建注释用于存储webapp数据的模型。打开Ajax图/notes/models.py让它看起来像这样:

    姜戈数据库进口模型注释模型.模型):标题=模型.查菲尔德最大长度=一百蛞蝓=模型.斯拉格菲尔德()文本=模型.文本字段空白的=无效的=DEF_ Unicode码__自己):返回U”注(%s%s%自己.标题自己.蛞蝓DEF获取绝对URL自己):返回u/注/%s/%自己.蛞蝓

    通过定义获取绝对URL方法已经,因为我们还没有写相应的URL,但我们现在这么做只是为了节省一点时间。

    之后,转到命令行并同步数据库,为注释模型创建适当的表。

    python管理.py同步数据库
  8. 现在我们可以写Ajax图/notes/urls.py文件。

    django.conf.urls.defaults进口*模型进口注释笔记=注释.物体.全部的()URL模式=模式R′^ $'django.views.generic.list_detail.object_list'双关语查询集=笔记R'^注/(?磷
               
                [-\w]+)/$'
               'django.views.generic.list_detail.object_detail'双关语查询集=笔记段塞鲁油田=“蛞蝓”R'^创建/$''备注.视图.创建备注'R'^注/(?磷
               
                [-\w]+)/更新/$'
               '备注.视图.更新备注'

    对于所有显示内容的需要,我们将使用两个通用视图列表\u detail.object \u list列出\u detail.object \u detail.

    前者将显示所有注释,后者将根据蛞蝓在URL的regex中检测到参数。

    通用视图对一组查询对象进行操作,这就是为什么我们必须创造笔记查询集并将其传递给视图。

    我们还指定了两个自定义视图,创建注释更新注释我们需要手写,这将允许我们通过向笔记中发布数据来创建和更改笔记。

  9. 通用视图有一个简单的机制来确定用于显示对象的模板。对于列表视图,它将尝试加载appname/modelname_list.html,对于细节视图,它将尝试加载appname/modelname_detail.html.

    在这种情况下,他们会备注/备注列表.html备注/备注\u detail.html.

    所以我们的下一步是创建这两个模板,但首先我们要创建一个基本.html其他两个模板可以扩展以减少重复。

    注释/模板/目录生成名为的新文件基本.html,并填写以下代码:

    <span><span class=“cp”>%<span><span class=“k”>block<span><span class=“nv”>title<span><span class=“cp”>%.<span>notes.djapp<span class=“cp”>%<span><span class=“k”>endblock<span><span class=“cp”>%.<span><span class=“nt”>
               
                Re=
                “样式表”
                HREF=
                “/media/style.css”
                >
                
                
                
                
                 
                  类=
                  “容器”
                  >
                  {%
                  
                  内容
                  %}{%
                  端块
                  %}
                  
                 
               

这是一个非常简单的基本模板,它只为我们处理一些静态导入和基本的HTML结构。

注意在顶部,我们添加了一个样式表并导入了jquery库,我们还没有把它放在媒体/目录。我们再多走几步就可以了。

  • 下一步是创建备注/备注列表.html在索引页上显示注释列表的模板。

    创建文件ajax-tut/notes/templates/notes/note\u list.html文件,并添加以下内容:

    {%延伸“基.html”%}{%内容%}
             
              类=
              “新”
              >
              

    创建新便笺。

    方法= “邮政” 行动= “/创建/” > for = “标题” >书名 类型= “文本” 名字= “标题” ID= “标题” > for = “蛞蝓” >鼻涕虫 类型= “文本” 名字= “蛞蝓” ID= “蛞蝓” > 类型= “提交” 价值= “创建便笺” >
    类= “名单” >

    笔记

    ID= “备注” > {% 对于 对象 在里面 对象列表 %}
  • HREF= {{ 对象。获取\u绝对\u URL } > {{ 对象.标题 }
  • {% 外循环 %}
    {% 端块 %}

    我们正在创建一个用于创建新便笺的简单表单,以及一个简单的显示它们的有序列表。我们将表单的内容发送到/创建/网址它正好指向创建注释方法注释.视图.

    我们去实施吧。

  • 打开注释/视图.py,我们会实施创建注释.它需要确保它正在接收一个post请求,请求还包含值标题蛞蝓.

    否则,它将返回一条有帮助的错误消息。

    模型进口注释姜戈.http进口httpresponseredirect公司HTTP响应服务器错误DEF创建注释请求):错误消息=U“未发送Post数据。”如果请求.方法=“邮政”邮递=请求..复制()如果邮递.有\键“蛞蝓”邮递.有\键'标题'):蛞蝓=邮递[“蛞蝓”]如果注释.物体.滤波器蛞蝓=蛞蝓.计数()>错误消息=“弹头已经在使用中。”其他的标题=邮递['标题']新注释=注释.物体.创造标题=标题蛞蝓=蛞蝓返回httpresponseredirect公司新注释.获取绝对URL()其他的错误消息=u“发布数据不足(需要'slug'和'title'!)”返回HTTP响应服务器错误错误消息

    请注意,在第10行中,我们正在验证slug是否已经用于防止slug重复(这将阻止使用通用详细视图访问具有重复slug的任何一个注释)。

  • 我们一半的应用程序现在已经实现并且工作一致。我们可以查看注释列表,创造新的。我们只需要查看和编辑个别注释。

    我们继续前进。

    打开备注/模板/备注/备注\u detail.html给它注入生命:

    {%延伸“基.html”%}{%内容%}
           
            类=
            “标题”
            >
            
             
              HREF=
              “/”
              >回到指数
              
              
             
           
    类= “详细信息” > 方法= “邮政” 行动= “更新/” > 类= “文本” > for = “标题” >书名 类型= “文本” 名字= “标题” ID= “标题” 价值= {{ 对象.标题 } > for = “蛞蝓” >鼻涕虫 类型= “文本” 名字= “蛞蝓” ID= “蛞蝓” 价值= {{ 对象.slug } >
  • 名字= “文本” ID= “文本” > {{ 对象.text } 类= “提交” 类型= “提交” 价值= “更新注释” > {% 端块 %}

    这次表单将其内容发布到更新/,这是一个相对的URL,不像/创建/这是一个绝对的网址。

    这让生活变得更容易,但是,便条的slug已经包含在其URL中,因此,我们不必每次更新时都发布slug(当前表单确实会在每次发送时发布所有内容,但对于我们的Ajax混音,情况并不一定如此)。

  • 接下来我们要写更新注释,哪个视图将处理提交的表单数据备注\u detail.html.

    打开注释/视图.py并在已经存在的代码下面添加此函数:

    DEF更新注释请求蛞蝓):如果请求.方法=“邮政”邮递=请求..复制()笔记=注释.物体.得到蛞蝓=蛞蝓如果邮递.有\键“蛞蝓”):鼻涕虫=邮递[“蛞蝓”]如果笔记.蛞蝓! =鼻涕虫如果注释.物体.滤波器蛞蝓=鼻涕虫.计数()>错误消息=“鼻涕虫已经吃了。”返回HTTP响应服务器错误错误消息笔记.蛞蝓=鼻涕虫如果邮递.有\键'标题'):笔记.标题=邮递['标题']如果邮递.有\键“文本”):笔记.文本=邮递[“文本”]笔记.节约()返回httpresponseredirect公司笔记.获取绝对URL()错误消息=U“未发送Post数据。”返回HTTP响应服务器错误错误消息

    注意,这是一种相当灵活的更新方法,如果所有三个字段都存在,它将更新所有字段,但它也只能处理其中一个或两个字段的更新。

    在处理更新之前,我们再次验证slug是否已经在使用中(slug必须是唯一的)。

    最后,我们仍在尝试提供有用的错误消息,帮助用户找出他们做错了什么,这对于让我们的Ajax版本拥有良好的用户体验至关重要。

  • 呸。现在我们已经完成了网站的非Ajax版本,但在我们继续使用一些javascript之前,我们只需要应用一点CSS,就可以让整个系统看起来更容易接受。

    Ajax图特/媒体/文件夹创建名为的文件样式表,并将此CSS输入其中:

    身体{字体系列格鲁吉亚}.容器{宽度80%上边距2EM左边距汽车右边距汽车}/*备注\u list.html*/新的{水平对齐中心边境1PX固体灰色下边距1EM底部间隙1EM}名单{边境1PX固体灰色}名单H2{水平对齐中心}/*备注\u detail.html*/.标题{下边距2EM}.详细信息文本{水平对齐中心}.详细信息文本区域{上边距1EM宽度100%高度300 PX}.详细信息.提交{宽度50%左边距25%右边距25%}

    嘿,现在看起来真的有点帅。

  • 继续保存所有内容,然后运行dev服务器以确保代码中没有拼写错误:

    python manage.py运行服务器

    然后转到网址:http://127.0.0.1:8000/确保一切正常。

  • 玩儿它,在公园里散步,当你的眼睛不再因为盯着屏幕而受伤时,然后回来,我们将开始使用Ajax。

    邀请Ajax参加聚会

    既然我们有了一个有效的应用程序,现在是时候开始考虑如何将一些动态Ajax功能合并到应用程序中了。

    在我们深入了解细节之前,我想简要介绍一下Ajax的高级概念。简单地说,Ajax是关于使用带外异步通信来提供功能,而不实际离开到达的URL。

    良好地使用Ajax可以使您的Web应用程序更具响应性。糟糕的使用会使你的网络应用可怕的死亡陷阱。确保使用Ajax很重要,因为它实际上改善了您的站点,不是因为…好,事实上,没有其他理由使用它。

    从姜戈的角度来看,实现Ajax需要编写JavaScript来从客户端发送请求,并确保您已经编写了适当的视图来满足这些请求。

    通常,这意味着创建自定义视图以对相关数据进行JSON编码并将其返回到等待的javascript函数。

    然而,在这个例子中,我们要做的事情略有不同。我们已经编写了处理所需功能(创建和编辑注释)的视图,我们只需将它们与我们的javascript一起重用。

    然而。。。这些视图返回的是HTML而不是JSON,所以我们必须自己提取必要的数据。我们将使用正则表达式。如果你觉得这有点过于复杂,请记住,您可以通过简单地编写额外的视图来避免这种regex魔法,这些视图以JSON编码的形式返回必要的数据。

    我们开始吧。

    1. 第一步是下载jquery javascript库,你可以在这里下载.

      然后把它移到媒体/目录。

      mv ~ /下载/ jquery-1.2.6.min.js媒体

      我们已经将导入添加到基本.html模板,看起来像这样:

      <span><span class=“cp”>%<span><span class=“k”>block<span><span class=“nv”>title<span><span class=“cp”>%.<span>notes.djapp<span class=“cp”>%<span><span class=“k”>endblock<span><span class=“cp”>%.<span><span class=“nt”>
                 
                  Re=
                  “样式表”
                  HREF=
                  “/media/style.css”
                  >
                  
                  
                 

      然后jquery被“安装”。

    2. 我们要尝试的第一个半开度是改进音符的创建过程。

      事实上,尝试创建新便笺时,您输入注释的标题和段塞,然后点击创建。然后它会把你带到笔记的页面。

      我们要稍微改变一下。相反,创建新便笺时,指向新便笺的链接将显示在便笺列表的顶部,不离开页面。

      这使得一次创建多个笔记更容易,而且在创建注释后仍然可以很容易地访问它。

      为了实现这一点,我们将向备注/备注列表.html模板。

      打开备注/备注列表.html文件,然后把这段代码插入%endblock%模板标记。我要把它分成两个功能,但它们应该都在一个里面块。

      var创建注释=功能(){var标题=$“标题”瓦尔()var蛞蝓=$“鼻涕虫”瓦尔()如果标题! =& &蛞蝓! ={var数据={标题标题蛞蝓蛞蝓};var阿尔茨海默病={类型“邮政”网址“/创建/”数据数据完成完成};$.阿贾克斯阿尔茨海默病}其他的{//显示故障说明}返回};

      这个创建注释这里的函数是使用jquery阿贾克斯函数将异步请求发送到/创建/网址。它提取标题和slug输入的值,并将其作为post参数传递。

      它还指定了完成函数在收到响应时被调用。(我们将在一秒钟内查看该函数。)

      最后,重要的是创建注释返回值.为了覆盖HTML按钮(在本例中是提交输入)的默认单击行为,你必须返回false.否则,按钮的正常行为仍然会发生(在本例中,这意味着尝试创建两次相同的注释,并将用户重定向到错误页面,而不是新生成的注释)。

      这个完成处理响应的函数如下:

      var完成=功能物件地位{如果地位=“成功”{varTXT=物件.响应文本var标题=TXT.比赛/id=“标题”值=“”\w+“/igvar鼻涕虫=TXT.比赛/id=“slug”值=“”\w+“/igvar标题=标题.比赛/“\w+”/ig]代替/gvar蛞蝓=鼻涕虫.比赛/“\w+”/ig]代替/gvar纽利=$
    3. +蛞蝓+“>+标题+
    4. $“备注”预先准备纽利$“标题”瓦尔$“鼻涕虫”瓦尔}其他的{//显示故障说明}}

      这个完成函数有点复杂,因为我们要从响应中解析段塞和文本,正好是HTML。

      在我们提取数据之后,然后我们使用jquery创建一个新的

    5. 元素,并预先准备好
        .

        最后,我们要做的最后一件事是创建注释在表单中使用“提交”按钮的功能:

        $“创建”点击创建注释

        现在测试一下。这有点进步。

      1. 现在我们绕过了一个重要问题:错误处理。事实上,如果出了问题,那么用户就不知道发生了什么。这对用户来说是一件很卑鄙的事情,所以我们会改进的。

        此错误通知是我们将在备注\u detail.html模板也一样,所以我们要确保我们编写了可重用的代码并将其放入JS媒体目录中的文件。

        继续创建新文件媒体/注释.js,并用这个函数填充它:

        var显示错误=功能味精ELEM{varmsg_div=$

        +味精+

        msg_div.插入后ELEM法迪因“慢”使有生气({不透明度}五千淡出“慢”功能(){msg_div.去除();(});};

        这个显示错误函数使用指定的错误消息创建一个新的DIV元素,然后淡入,显示5秒钟,然后淡出(并删除DIV)。

        然后我们必须把它装进我们的基本.html模板,在加载jquery库下面添加此行:

        最后,我们必须把它整合到我们的备注/备注列表.html模板放在两个位置。

        替换:

        var完成=功能物件地位{如果地位=“成功”{//做事}其他的{//显示故障说明}}

        使用此代码可以实际处理错误:

        var完成=功能物件地位{如果地位=“成功”{//做事}其他的{//只有这个改变了…显示错误物件.响应文本$“新”);}}

        而在创建注释替换此行

        //显示故障说明

        有了这个:

        显示错误“需要标题和段塞的值。”$“新”);

        现在我们的Ajax注释创建实际上是可用的,而不是简单地成为用户不愉快导航的雷区。

        不知怎的,我们聚集了力量,继续深入这个可怕的新大陆。

      2. 现在我们要把焦点从备注/备注列表.html到细节模板,备注/备注\u detail.html.

        我们将实现两个可爱的想法:

        1. slug和title输入将转换为纯文本,直到鼠标悬停在它们上面。在这一点上,它们将变成输入。

        2. 我们要让提交按钮消失,并在离开相应的输入或文本字段后立即更新数据。

        一开始我们要做的很简单,然后再把它修好一点。

        去开门吧备注/备注\u detail.html.

        就在%endblock%标记我们要添加另一个块。

        现在我们要做一些我们没有做的事备注\u list.html,但可能应该有。我们将把所有的javascript包装在这个函数中:

        $文件准备好的功能(){//做事(});

        这是一个很有帮助的jquery技巧,可以确保在DOM数据可供操作之后加载JavaScript。从本质上讲,它可以确保在调用脚本时页面仍然不会构建自身(这可能会妨碍脚本正确执行)。

        现在,在这个函数中,我们将首先让输入在鼠标不在其上时变为跨距。让我们从标题输入开始。

        $文件准备好的功能(){var标题输入=功能(){var标题=$“标题”var输入=$+标题.文本()+“>输入.悬停功能(){}标题标题.替换为输入}var标题=功能(){//鼠标离开时调用var标题=$“标题”var跨度=$+标题.瓦尔()+跨度.悬停标题输入功能(){};标题.替换为跨度}(});

        您可以看到我们开始在这里使用更多的jquery。这个悬停函数允许您指定当鼠标位于元素上方时要调用的函数,以及在离开元素时要调用的第二个函数。

        我们使用它来调用函数来在输入和跨度之间进行转换。我用的是冗长的风格,但毫无疑问,您可以将JavaScript压缩到更少的行…但我发现它更清晰。

        我们还需要为slug输入编写等效函数。把这些扔到里面$(document.ready())功能也一样:

        var段塞输入=功能(){var蛞蝓=$“鼻涕虫”var输入=$+蛞蝓.文本()+“>输入.悬停功能(){}段塞流到段塞流蛞蝓.替换为输入}var段塞流到段塞流=功能(){//鼠标离开时调用var蛞蝓=$“鼻涕虫”var跨度=$+蛞蝓.瓦尔()+跨度.悬停段塞输入功能(){};蛞蝓.替换为跨度}标题();段塞流到段塞流();

        如你所见,我们还需要打电话给他们_到范围在页面加载时执行一次函数,使它们以跨度开始。

        继续在页面上测试它。

        你可能会觉得这很烦人,因为调整大小确实改变了事情的方向。让我们把几行CSS放到样式表帮助减轻压力。

        第一,删除这些行:

        .详细信息文本{水平对齐中心}

        然后。。。放弃。有可能让这项技术看起来不错,但我们需要在标记中添加一些分隔符,而本教程并不是为了达到完美的视觉效果。

      3. 现在我们有了输入在跨度和输入之间的切换,但我们仍然需要使用“OLE风格”按钮提交数据。

        所以,首先,让我们去掉这个按钮(对于启用了javascript的人而言)。然后让我们在鼠标离开编辑字段时保存来替换它的功能。

        为了摆脱提交按钮,我们只需将这一行javascript添加到我们已经拥有的内容中(在准备就绪()功能):

        $“输入[类型=提交]”去除()

        更新只是稍微复杂一点。

      4. 在实施更新之前,我们将走一条简短的弯路来创建一个显示成功函数来补充显示错误我们以前创建的函数。

        去吧,打开媒体/注释.js并添加此函数:

        var显示成功=功能味精ELEM{varmsg_div=$

        +味精+

        msg_div.插入后ELEM法迪因“慢”使有生气({不透明度}五千淡出“慢”功能(){msg_div.去除();(});};

        然后我们将对两个显示成功显示错误功能。打开媒体/样式.css并添加这些行:

        .error_msg{背景色红色边境1PX固体黑色上边距1EM下边距1EM水平对齐中心}.成功消息{背景色蓝色边境1PX固体黑色上边距1EM下边距1EM水平对齐中心}

        这种CSS可以很容易地区分成功消息和错误消息,让它们看起来更漂亮。

      5. 现在,我们准备将更新添加到备注/备注\u detail.html.我们将在这一步中修改大量的代码,所以首先,我会看看各个部分,然后显示它的整体(以便于复制粘贴)。

        第一,我们需要创建一个函数,用于将更新发送到更新/网址。

        var执行更新=功能领域瓦尔{var数据={};数据[领域]=瓦尔var阿尔茨海默病={类型“邮政”网址“更新/”数据数据完成完成};$.阿贾克斯阿尔茨海默病};

        使用此函数更新值非常简单:

        执行更新“标题”“我的头衔”执行更新“蛞蝓”“我的鼻涕虫”执行更新“文本”“那是一段美好的时光”

        记住我们做了更新查看注释.视图足够灵活,可以同时处理接收所有值,或者一次处理一个值的接收,它允许我们编写这个简单的更新函数。

        还要注意执行更新正在校准完成完成时的功能,我们还没有写出来。完成如下所示:

        var完成=功能物件地位{如果地位=“成功”显示成功“更新成功。”$“.文本”);其他的显示错误物件.响应文本$“.文本”);}

        它使用我们的帮助显示错误显示成功函数来处理大部分细节。

        最后,我们必须修改标题段塞流到段塞流调用发送更新的函数。

        这很简单,只需将它们更改为:

        var标题=功能(){var标题=$“标题”执行更新“标题”标题.瓦尔())//等等}

        但这导致了一个问题:我们称之为_到范围函数加载页面时,所以我们会在加载页面时立即发送更新。

        我们可以通过使用一对变量来跟踪这是否是最初的用法来防止这种情况。防止在这种情况下发送更新。

        var初始标题更改=var姓名首字母变更=var段塞流到段塞流=功能(){var蛞蝓=$“鼻涕虫”如果姓名首字母变更姓名首字母变更=其他的执行更新“蛞蝓”蛞蝓.瓦尔())//等等}

        有了这一变化,我们的工作就顺利了,以及整个代码块块)如下所示:

        $文件准备好的功能(){var初始标题更改=var姓名首字母变更=var执行更新=功能领域瓦尔{var数据={};数据[领域]=瓦尔var阿尔茨海默病={类型“邮政”网址“更新/”数据数据完成完成};$.阿贾克斯阿尔茨海默病};var完成=功能物件地位{如果地位=“成功”显示成功“更新成功。”$“.文本”);其他的显示错误物件.响应文本$“.文本”);}var标题输入=功能(){var标题=$“标题”var输入=$+标题.文本()+“>输入.悬停功能(){}标题标题.替换为输入}var标题=功能(){//鼠标离开时调用var标题=$“标题”如果初始标题更改初始标题更改=其他的执行更新“标题”标题.瓦尔())var跨度=$+标题.瓦尔()+跨度.悬停标题输入功能(){};标题.替换为跨度}var段塞输入=功能(){var蛞蝓=$“鼻涕虫”var输入=$+蛞蝓.文本()+“>输入.悬停功能(){}段塞流到段塞流蛞蝓.替换为输入}var段塞流到段塞流=功能(){//鼠标离开时调用var蛞蝓=$“鼻涕虫”如果姓名首字母变更姓名首字母变更=其他的执行更新“蛞蝓”蛞蝓.瓦尔())var跨度=$+蛞蝓.瓦尔()+跨度.悬停段塞输入功能(){};蛞蝓.替换为跨度}标题();段塞流到段塞流();$“输入[类型=提交]”去除()(});

        就几行…正确的?

      6. 敏锐的读者,或者激进的批评家,我们会很快注意到,这种实现有很多方法是不完美的。

        例如,如果它特别提到哪个字段被更新了,这不是很好吗?更好的是,如果在更新失败时恢复所有更改,这不是很好吗?

        是的。那就太好了。然而,实现这些视图需要我们编写额外的自定义视图,以向我们提供在这些情况下所需的知识。

        例如,Ajax友好的更新方法可能如下所示:

        Django.utils公司进口单工DEFAjax_更新说明请求蛞蝓):邮递=请求..复制()笔记=注释.物体.得到蛞蝓=蛞蝓如果邮递.有\键“蛞蝓”):鼻涕虫=邮递[“蛞蝓”]如果注释.物体.滤波器蛞蝓=鼻涕虫.计数()>D={“味精”“slug已经在使用中。”“蛞蝓”笔记.蛞蝓}返回HTT响应单工.转储D笔记.蛞蝓=鼻涕虫如果邮递.有\键'标题'):笔记.标题=邮递['标题']如果邮递.有\键“文本”):笔记.文本=邮递[“文本”]D={“味精”'更新成功!'}返回HTT响应单工.转储D

        如果我们使用它,然后我们有足够的数据来将无效的更改恢复到以前的值,如果不做修改,我们可能会更加幻想。

        本教程不会明确地沿着这条路走,但如果您简单地创建一个新的url regex注释.urls,粘贴到上面Ajax_更新说明请求,并修改执行更新功能备注/备注\u detail.html,那你就快完成了。

        你必须重写完成也,利用传入的JSON。它可能看起来像:

        var完成=功能物件地位{如果地位=“成功”{var数据=埃瓦物件.响应文本显示成功数据[“味精”]$“.文本”);其他的{var数据=埃瓦物件.响应文本显示错误数据[“味精”]$“.文本”);如果数据.蛞蝓{$“鼻涕虫”文本数据.蛞蝓}}}

        当您开始编写更复杂的Ajax功能时,然后,您将不可避免地需要编写自定义的Django视图来支持该功能。

        这只是做(Ajax)业务的成本。

      7. 最后,我们还需要设置文本字段进行更新。因为我们已经编写了实用程序函数,这将非常迅速:

        $“文本”悬停功能(){}功能(){执行更新“文本”$“文本”文本())(});

        添加该行,以便在备注/备注\u detail.html如下所示:

        标题();段塞流到段塞流();$“文本”悬停功能(){}功能(){执行更新“文本”$“文本”文本())(});$“输入[类型=提交]”去除()

        现在它像文本字段一样更新。

      notes.djapp详细视图的屏幕截图。

      虽然不是很精致,我们在这里实现了一些有趣的Ajax功能,希望足够让你开始实施自己的想法。

      继续前进

      在本教程中,我们将一个漂亮的计划应用程序转换成了一个稍微令人兴奋的应用程序。我们暂时不谈这个,你可以在这里下载Git存储库的zip.

      我将在两篇补充文章中讨论另外两个主题:

      1. 使用其他视图改善Ajax体验,和
      2. 向此应用程序添加验证层。

      第二部分在这里继续。


      1. 当然,浏览器无法运行javascript的个人越来越少。有一段时间,许多移动浏览器都在与JS抗争,但在这一点上,这似乎已经成为过去了。

        确实有人出于安全原因禁用了javascript,但即使在这一小部分之外,设计不需要JavaScript的网站有好处。

        第一,它在客户机和服务器之间促进标准和可预测的API(发布或获取Win请求)。第二个,它使你的网站更容易为两个可访问性的目的而爬行,以及搜索引擎。γ