在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 相关文章推荐
wxpython 学习笔记 第一天
Mar 16 Python
Python读写配置文件的方法
Jun 03 Python
在Django中限制已登录用户的访问的方法
Jul 23 Python
Python内建函数之raw_input()与input()代码解析
Oct 26 Python
Python面向对象之静态属性、类方法与静态方法分析
Aug 24 Python
python 使用递归实现打印一个数字的每一位示例
Feb 27 Python
在pycharm中关掉ipython console/PyDev操作
Jun 09 Python
使用keras实现孪生网络中的权值共享教程
Jun 11 Python
PyCharm Community安装与配置的详细教程
Nov 24 Python
Python使用sql语句对mysql数据库多条件模糊查询的思路详解
Apr 12 Python
python爬取豆瓣电影TOP250数据
May 23 Python
Python基本数据类型之字符串str
Jul 21 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
snoopy 强大的PHP采集类使用实例代码
2010/12/09 PHP
Yii2.0表关联查询实例分析
2016/07/18 PHP
几个比较实用的JavaScript 测试及效验工具
2010/04/18 Javascript
js屏蔽鼠标键盘(右键/Ctrl+N/Shift+F10/F11/F5刷新/退格键)
2013/01/24 Javascript
JavaScript中检测变量是否存在遇到的一些问题
2013/11/11 Javascript
JS实现无限级网页折叠菜单(类似树形菜单)效果代码
2015/09/17 Javascript
Javascript中的数据类型之旅
2015/10/18 Javascript
jquery实现模拟百分比进度条渐变效果代码
2015/10/29 Javascript
探析浏览器执行JavaScript脚本加载与代码执行顺序
2016/01/12 Javascript
jQuery中数据缓存$.data的用法及源码完全解析
2016/04/29 Javascript
knockoutjs模板实现树形结构列表
2017/07/31 Javascript
JavaScript实现图片拖曳效果
2017/09/08 Javascript
微信小程序实现默认第一个选中变色效果
2018/07/17 Javascript
微信小程序利用swiper+css实现购物车商品删除功能
2019/03/06 Javascript
使用Vue父子组件通信实现todolist的功能示例代码
2019/04/11 Javascript
如何换个角度使用VUE过滤器详解
2019/09/11 Javascript
vue cli4下环境变量和模式示例详解
2020/04/09 Javascript
js实现类选择器和name属性选择器的示例步骤
2021/02/07 Javascript
[02:51]2014DOTA2 TI小组赛总结中国军团全部进军钥匙球馆
2014/07/15 DOTA
[39:02]DOTA2亚洲邀请赛 3.31 小组赛 B组 Mineski vs VGJ.T
2018/04/01 DOTA
Python使用pylab库实现绘制直方图功能示例
2018/06/01 Python
浅谈Python2、Python3相对路径、绝对路径导入方法
2018/06/22 Python
浅析Python 引号、注释、字符串
2019/07/25 Python
详解python 降级到3.6终极解决方案
2020/02/06 Python
pandas使用之宽表变窄表的实现
2020/04/12 Python
Python填充任意颜色,不同算法时间差异分析说明
2020/05/16 Python
时尚的CSS3进度条效果
2012/02/22 HTML / CSS
Joseph官网:英国小众奢侈品牌
2019/05/17 全球购物
Zatchels官网:英国剑桥包品牌
2021/01/12 全球购物
北京SQL新华信咨询
2016/09/30 面试题
后勤部长岗位职责
2013/12/14 职场文书
法学院方阵解说词
2014/01/29 职场文书
新生入学欢迎词
2015/01/26 职场文书
客房领班岗位职责
2015/02/11 职场文书
大学生先进个人主要事迹材料
2015/11/04 职场文书
原来闭幕词是这样写的呀!
2019/07/01 职场文书