Skip to content

Latest commit

 

History

History
192 lines (137 loc) · 7.4 KB

10-expand-todos-with-server.rst

File metadata and controls

192 lines (137 loc) · 7.4 KB

第十章 实战演练:扩展todos到Server端(backbonejs+webpy)

上一节简单介绍了怎么使用webpy搭建一个后端的接口服务,这一节就来简单实现一下。

10.1 项目结构

首先还是来看下项目的结构,然后再一步一步的分析,结构如下:

src
├── index.html
├── init_sqlite.py
├── models.py
├── server.py
├── static
│   ├── backbone.js
│   ├── destroy.png
│   ├── jquery.js
│   ├── json2.js
│   ├── todos.css
│   ├── todos.js
│   └── underscore.js
└── todos.db

以上结构可以分为四个部分:模板、静态资源、后端逻辑处理、后端数据处理,其实最后两个都属于后端部分。

因为模板和静态资源和之前没有太大差异,因此合并在一起介绍。首先来看后端的接口。

10.2 后端接口

相对于前端的各种model、collection和view,后端显得比较简单。只需要提供可访问的接口,并且根据POST、PUT、DELETE、GET这四种操作完成对数据库的CRUD即可(Create,Read,Update,Delete)。

先来看models中的代码,这里对todo表的操作进行了简单的封装:

#coding:utf-8
import web

db = web.database(dbn='sqlite', db="todos.db")

class Todos(object):
    @staticmethod
    def get_by_id(id):
        return db.select('todos', where="id=$id", vars=locals())

    @staticmethod
    def get_all():
        return db.select('todos')

    @staticmethod
    def create(**kwargs):
        db.insert('todos', **kwargs)

    @staticmethod
    def update(**kwargs):
        db.update('todos', where="id=$id", vars={"id": kwargs.pop('id')}, **kwargs)

    @staticmethod
    def delete(id):
        db.delete('todos', where="id=$id", vars=locals())

代码很简单,从方法的命名上就知道要完成的功能是什么,这里不得不说一句,任何语言中好的变量或方法的命名,胜过大段的注释。

model部分没有具体的业务逻辑,只是针对数据库进行CRUD操作。下面来看给浏览器提供接口的部分。

server部分,提供了前端浏览器需要访问的接口,同时也提供了页面初始加载时的渲染页面的功能。server.py的代码如下:

#coding:utf-8
import json

import web
from models import Todos

urls = (
    '/', 'index',  #返回首页
    #  处理POST请求
    '/todo', 'todo',
    # 处理前端todo的请求,对指定记录进行操作
    '/todo/(\d*)', 'todo',
    # 处理前端todo的请求,返回所有数据
    '/todos/', 'todos',
)

app = web.application(urls, globals())

render = web.template.render('')

# 首页
class index:
    def GET(self):
        # 渲染首页到浏览器
        return render.index()

class todo:
    def GET(self, todo_id=None):
        result = None
        itertodo = Todos.get_by_id(id=todo_id)
        for todo in itertodo:
            result = {
                "id": todo.id,
                "title": todo.title,
                "order": todo._order,
                "done": todo.done == 1,
            }
        return json.dumps(result)

    def POST(self):
        data = web.data()
        todo = json.loads(data)
        # 转换成_order, order是数据库关键字, sqlite3报错
        todo['_order'] = todo.pop('order')
        Todos.create(**todo)

    def PUT(self, todo_id=None):
        data = web.data()
        todo = json.loads(data)
        todo['_order'] = todo.pop('order')
        Todos.update(**todo)

    def DELETE(self, todo_id=None):
        Todos.delete(id=todo_id)


class todos:
    def GET(self):
        todos = []
        itertodos = Todos.get_all()
        for todo in itertodos:
            todos.append({
                "id": todo.id,
                "title": todo.title,
                "order": todo._order,
                "done": todo.done == 1,
            })
        return json.dumps(todos)

if __name__ == "__main__":
    app.run()

相对于model.py来说,这里做了些数据转换的操作,如前端backbone通过ajax发过来的数据需要转换之后才能存入数据库,而从数据库取出的数据也要稍加处理才能符合前端todos.js中定义的model的要求。

在这个server中,提供了三个四个url,依次功能为:首页加载、单个todo创建、单个todo查询修改和删除、查询全部。分成四个也主要是依据所选框架webpy的特性。

在url之后,是对应一个具体的class,url接受到的请求将有对应的class来处理,比如说 /todo 这个url,对应的处理请求的class就是todo。另外对应浏览器端发过来的POST、GET、PUT、DELETE请求,class对应的也是相应的方法。这也是选webpy的一个原因。

说我了后端提供的接口,以及如何进行处理的原理。我们来看如何修改前端的代码,才能让数据发送到后端来。

10.3 修改todos,发送数据到后端

这个部分改动比较小,就不贴代码了。有需要的可以到 code 中看。

之前的数据是存在localstorage中,是因为引用了localStorage.js文件,并且在collection中声明了 localStorage: new Backbone.LocalStorage("todos-backbone")

在修改的时候有三个地方需要修改,第一是model的定义,部分代码:

var Todo = Backbone.Model.extend({
    urlRoot: '/todo',
    ......

第二个就是collection的修改,去掉了localStorage的声明,并添加url:

var TodoList = Backbone.Collection.extend({
    url: '/todos/',
    ......

这样就搞定了。

10.4 Demo的使用

code 中,如果想要把我的demo在本地运行的话,需要首先运行下 python init_sqlite.py 来初始化sqlite3的数据库,运行完之后会在本地生成一个todos.db的数据库文件。

之后,就可以通过运行 python server.py ,然后访问命令行提示的网址就可以使用了。

最后稍稍总结一下,我觉得到这一章为止,对技术比较认真、比较有追求的同学应该知道怎么通过backbonejs和webpy把前后端连起来了。所有的这些文章只是为了帮你打开一扇门,或者仅仅只是一盏灯,具体你的业务逻辑还是需要通过自己的思考来解决。妄图让别人帮你实现业务逻辑的人都是切实的不思上进的菜鸟。

另外,关于这个Todos的案例,是你在打算把Backbonejs应用于实践时必须要参考和思考的。虽然到网上搜罗一下 Backbonejs项目实例 比思考要省心,但是别人的始终是别人的,你不转化成自己的,始终无法灵活运用。借此告诫那些觉得这个Todo案例没啥用的同学们。

导航