在Python的web框架中编写创建日志的程序的教程


Posted in Python onApril 30, 2015

在Web开发中,后端代码写起来其实是相当容易的。

例如,我们编写一个REST API,用于创建一个Blog:

@api
@post('/api/blogs')
def api_create_blog():
  i = ctx.request.input(name='', summary='', content='')
  name = i.name.strip()
  summary = i.summary.strip()
  content = i.content.strip()
  if not name:
    raise APIValueError('name', 'name cannot be empty.')
  if not summary:
    raise APIValueError('summary', 'summary cannot be empty.')
  if not content:
    raise APIValueError('content', 'content cannot be empty.')
  user = ctx.request.user
  blog = Blog(user_id=user.id, user_name=user.name, name=name, summary=summary, content=content)
  blog.insert()
  return blog

编写后端Python代码不但很简单,而且非常容易测试,上面的API:api_create_blog()本身只是一个普通函数。

Web开发真正困难的地方在于编写前端页面。前端页面需要混合HTML、CSS和JavaScript,如果对这三者没有深入地掌握,编写的前端页面将很快难以维护。

更大的问题在于,前端页面通常是动态页面,也就是说,前端页面往往是由后端代码生成的。

生成前端页面最早的方式是拼接字符串:

s = '<html><head><title>'
 + title
 + '</title></head><body>'
 + body
 + '</body></html>'

显然这种方式完全不具备可维护性。所以有第二种模板方式:

<html>
<head>
  <title>{{ title }}</title>
</head>
<body>
  {{ body }}
</body>
</html>

ASP、JSP、PHP等都是用这种模板方式生成前端页面。

如果在页面上大量使用JavaScript(事实上大部分页面都会),模板方式仍然会导致JavaScript代码与后端代码绑得非常紧密,以至于难以维护。其根本原因在于负责显示的HTML DOM模型与负责数据和交互的JavaScript代码没有分割清楚。

要编写可维护的前端代码绝非易事。和后端结合的MVC模式已经无法满足复杂页面逻辑的需要了,所以,新的MVVM:Model View ViewModel模式应运而生。

MVVM最早由微软提出来,它借鉴了桌面应用程序的MVC思想,在前端页面中,把Model用纯JavaScript对象表示:

<script>
var blog = {
  name: 'hello',
  summary: 'this is summary',
  content: 'this is content...'
};
</script>

View是纯HTML:

<form action="/api/blogs" method="post">
  <input name="name">
  <input name="summary">
  <textarea name="content"></textarea>
  <button type="submit">OK</button>
</form>

由于Model表示数据,View负责显示,两者做到了最大限度的分离。

把Model和View关联起来的就是ViewModel。ViewModel负责把Model的数据同步到View显示出来,还负责把View的修改同步回Model。

ViewModel如何编写?需要用JavaScript编写一个通用的ViewModel,这样,就可以复用整个MVVM模型了。

好消息是已有许多成熟的MVVM框架,例如AngularJS,KnockoutJS等。我们选择Vue这个简单易用的MVVM框架来实现创建Blog的页面templates/manage_blog_edit.html:

{% extends '__base__.html' %}

{% block title %}编辑日志{% endblock %}

{% block beforehead %}

<script>
var
  action = '{{ action }}',
  redirect = '{{ redirect }}';

var vm;

$(function () {
  vm = new Vue({
    el: '#form-blog',
    data: {
      name: '',
      summary: '',
      content: ''
    },
    methods: {
      submit: function (event) {
        event.preventDefault();
        postApi(action, this.$data, function (err, r) {
          if (err) {
            alert(err);
          }
          else {
            alert('保存成功!');
            return location.assign(redirect);
          }
        });
      }
    }
  });
});
</script>
{% endblock %}

{% block content %}
<div class="uk-width-1-1">
  <form id="form-blog" v-on="submit: submit" class="uk-form uk-form-stacked">
    <div class="uk-form-row">
      <div class="uk-form-controls">
        <input v-model="name" class="uk-width-1-1">
      </div>
    </div>
    <div class="uk-form-row">
      <div class="uk-form-controls">
        <textarea v-model="summary" rows="4" class="uk-width-1-1"></textarea>
      </div>
    </div>
    <div class="uk-form-row">
      <div class="uk-form-controls">
        <textarea v-model="content" rows="8" class="uk-width-1-1"></textarea>
      </div>
    </div>
    <div class="uk-form-row">
      <button type="submit" class="uk-button uk-button-primary">保存</button>
    </div>
  </form>
</div>
{% endblock %}

初始化Vue时,我们指定3个参数:

el:根据选择器查找绑定的View,这里是#form-blog,就是id为form-blog的DOM,对应的是一个<form>标签;

data:JavaScript对象表示的Model,我们初始化为{ name: '', summary: '', content: ''};

methods:View可以触发的JavaScript函数,submit就是提交表单时触发的函数。

接下来,我们在<form>标签中,用几个简单的v-model,就可以让Vue把Model和View关联起来:

<!-- input的value和Model的name关联起来了 -->
<input v-model="name" class="uk-width-1-1">

Form表单通过<form v-on="submit: submit">把提交表单的事件关联到submit方法。

需要特别注意的是,在MVVM中,Model和View是双向绑定的。如果我们在Form中修改了文本框的值,可以在Model中立刻拿到新的值。试试在表单中输入文本,然后在Chrome浏览器中打开JavaScript控制台,可以通过vm.name访问单个属性,或者通过vm.$data访问整个Model:

在Python的web框架中编写创建日志的程序的教程

如果我们在JavaScript逻辑中修改了Model,这个修改会立刻反映到View上。试试在JavaScript控制台输入vm.name = 'MVVM简介',可以看到文本框的内容自动被同步了:

在Python的web框架中编写创建日志的程序的教程

双向绑定是MVVM框架最大的作用。借助于MVVM,我们把复杂的显示逻辑交给框架完成。由于后端编写了独立的REST API,所以,前端用AJAX提交表单非常容易,前后端分离得非常彻底。

Python 相关文章推荐
Python 第一步 hello world
Sep 25 Python
Python中的jquery PyQuery库使用小结
May 13 Python
Python使用urllib模块的urlopen超时问题解决方法
Nov 08 Python
python中matplotlib实现最小二乘法拟合的过程详解
Jul 11 Python
基于Django contrib Comments 评论模块(详解)
Dec 08 Python
python实现字符串加密 生成唯一固定长度字符串
Mar 22 Python
Python中面向对象你应该知道的一下知识
Jul 10 Python
Python基于Tkinter编写crc校验工具
May 06 Python
Django 允许局域网中的机器访问你的主机操作
May 13 Python
Python实现初始化不同的变量类型为空值
Jun 02 Python
完美解决python针对hdfs上传和下载的问题
Jun 05 Python
python读写数据读写csv文件(pandas用法)
Dec 14 Python
用Python实现web端用户登录和注册功能的教程
Apr 30 #Python
用Python编写web API的教程
Apr 30 #Python
为Python的web框架编写前端模版的教程
Apr 30 #Python
为Python的web框架编写MVC配置来使其运行的教程
Apr 30 #Python
在Python的web框架中配置app的教程
Apr 30 #Python
python实现从ftp服务器下载文件的方法
Apr 30 #Python
简单介绍Python下自己编写web框架的一些要点
Apr 29 #Python
You might like
jq的get传参数在utf-8中乱码问题的解决php版
2008/07/23 PHP
php 购物车的例子
2009/05/04 PHP
PHP上传文件参考配置大文件上传
2015/12/16 PHP
我整理的PHP 7.0主要新特性
2016/01/07 PHP
php mysql_real_escape_string addslashes及mysql绑定参数防SQL注入攻击
2016/12/23 PHP
浅谈PHP中如何实现Hook机制
2017/11/14 PHP
基于jquery的关于动态创建DOM元素的问题
2010/12/24 Javascript
jquery插件制作 自增长输入框实现代码
2012/08/17 jQuery
解析jquery中的ajax缓存问题
2013/12/19 Javascript
关闭页面window.location事件未执行的原因及解决方法
2014/09/01 Javascript
跟我学习javascript的prototype,getPrototypeOf和__proto__
2015/11/17 Javascript
JS点击某个图标或按钮弹出文件选择框的实现代码
2016/09/27 Javascript
原生js的RSA和AES加密解密算法
2016/10/08 Javascript
jquery在vue脚手架中的使用方式示例
2017/08/29 jQuery
详解JavaScript中typeof与instanceof用法
2018/10/24 Javascript
浅谈vue3中effect与computed的亲密关系
2019/10/10 Javascript
Vue v-for循环之@click点击事件获取元素示例
2019/11/09 Javascript
微信小程序学习总结(三)条件、模板、文件引用实例分析
2020/06/04 Javascript
[52:02]DOTA2-DPC中国联赛 正赛 Phoenix vs Dragon BO3 第二场 2月26日
2021/03/11 DOTA
Python实现删除文件但保留指定文件
2015/06/21 Python
Django返回json数据用法示例
2016/09/18 Python
Django 创建/删除用户的示例代码
2019/07/24 Python
解决django后台管理界面添加中文内容乱码问题
2019/11/15 Python
python实现替换word中的关键文字(使用通配符)
2020/02/13 Python
Django 设置admin后台表和App(应用)为中文名的操作方法
2020/05/10 Python
Python 合并拼接字符串的方法
2020/07/28 Python
pyqt5 textEdit、lineEdit操作的示例代码
2020/08/12 Python
用ldap作为django后端用户登录验证的实现
2020/12/07 Python
丑小鸭教学反思
2014/02/03 职场文书
学校地质灾害防治方案
2014/06/10 职场文书
日语专业毕业生自荐书
2014/06/18 职场文书
学习朴航瑛老师爱岗敬业先进事迹思想汇报
2014/09/17 职场文书
学校运动会报道稿
2014/09/23 职场文书
房屋产权证明书
2014/10/15 职场文书
运动会入场词
2015/07/18 职场文书
2016年暑假家长对孩子评语
2015/12/01 职场文书