在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基于xml parse实现解析cdatasection数据
Sep 30 Python
Python中%r和%s的详解及区别
Mar 16 Python
Python实现图片滑动式验证识别方法
Nov 09 Python
python使用Tkinter实现在线音乐播放器
Jan 30 Python
python保存文件方法小结
Jul 27 Python
python 实现12bit灰度图像映射到8bit显示的方法
Jul 08 Python
Python中BeautifuSoup库的用法使用详解
Nov 15 Python
python实现双色球随机选号
Jan 01 Python
python安装读取grib库总结(推荐)
Jun 24 Python
Python中用xlwt制作表格实例讲解
Nov 05 Python
Python爬虫定时计划任务的几种常见方法(推荐)
Jan 15 Python
http通过StreamingHttpResponse完成连续的数据传输长链接方式
Feb 12 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
用mysql内存表来代替php session的类
2009/02/01 PHP
PHP mail 通过Windows的SMTP发送邮件失败的解决方案
2009/05/27 PHP
推荐一本PHP程序猿都应该拜读的书
2014/12/31 PHP
ThinkPHP中类的构造函数_construct()与_initialize()的区别详解
2017/03/13 PHP
基于thinkphp5框架实现微信小程序支付 退款 订单查询 退款查询操作
2020/08/17 PHP
Prototype使用指南之selector.js
2007/01/10 Javascript
javascript 对象比较实现代码
2009/04/27 Javascript
js下用eval生成JSON对象
2010/09/17 Javascript
jQuery EasyUI API 中文文档 - Tabs标签页/选项卡
2011/10/01 Javascript
jquery 实现checkbox全选,反选,全不选等功能代码(奇数)
2012/10/24 Javascript
js 获取class的元素的方法 以及创建方法getElementsByClassName
2013/03/11 Javascript
JavaScript实现在数组中查找不同顺序排列的字符串
2014/09/26 Javascript
ECMAScript6函数剩余参数(Rest Parameters)
2015/06/12 Javascript
谈谈JavaScript类型系统之Math
2016/01/06 Javascript
详述JavaScript实现继承的几种方式(推荐)
2016/03/22 Javascript
JavaScript事件学习小结(三)js事件对象
2016/06/09 Javascript
jQuery中的一些常见方法小结(推荐)
2016/06/13 Javascript
通过bootstrap全面学习less
2016/11/09 Javascript
JavaScript中${pageContext.request.contextPath}取值问题及解决方案
2016/12/08 Javascript
微信小程序左滑删除效果的实现代码
2017/02/20 Javascript
vue-cli与webpack处理静态资源的方法及webpack打包的坑
2018/05/15 Javascript
前端Vue项目详解--初始化及导航栏
2019/06/24 Javascript
在Layui 的表格模板中,实现layer父页面和子页面传值交互的方法
2019/09/10 Javascript
vue.js自定义组件实现v-model双向数据绑定的示例代码
2020/01/08 Javascript
[57:37]EG vs Mineski 2018国际邀请赛小组赛BO2 第二场 8.16
2018/08/17 DOTA
Python中replace方法实例分析
2014/08/20 Python
使用python将大量数据导出到Excel中的小技巧分享
2018/06/14 Python
windows下的pycharm安装及其设置中文菜单
2020/04/23 Python
基于Pytorch版yolov5的滑块验证码破解思路详解
2021/02/25 Python
中国跨境在线时尚零售商:Bellelily
2018/04/06 全球购物
电子邮箱格式怎么写
2014/01/12 职场文书
高一英语教学反思
2014/01/22 职场文书
企业安全生产演讲稿
2014/05/09 职场文书
2014年组织委员工作总结
2014/12/01 职场文书
升职感谢信
2015/01/22 职场文书
导游词之山西关帝庙
2019/11/01 职场文书