我正在探索使用 CherryPy 作为后端和 emberjs 作为管理书籍列表的简单 Web 应用程序的前端。Cherrypy 只是根据索引请求提供车把模板:
import os
import cherrypy
from google.appengine.api import users
from google.appengine.ext import ndb
class Root:
def __init__(self):
# book REST API
self.books = BookAPI()
@cherrypy.expose
def index(self):
return open(os.path.join(template_env, 'index.hbs'))
我使用 BooksAPI 和 Books 类作为 RESTfull API,使用 Google 数据存储来存储图书对象(我现在只存储 isbn)。
class BookAPI():
exposed=True
@cherrypy.tools.json_out()
def GET(self, isbn=None):
# get the current user
user = users.get_current_user()
if(isbn is None):
# query all books current user
ancestor_key = ndb.Key("Library", str(user.user_id()))
books = Book.query_books(ancestor_key).fetch(20)
# convert to JSON list of books
book_list = []
for index, b in enumerate(books):
book_list.append({'id': index, 'isbn': b.isbn})
result = {
"books": book_list
}
return result
def POST(self, isbn):
# get the current user
user = users.get_current_user()
# create book and save in data storage
parent_key = ndb.Key('Library', user.user_id())
book = Book(parent=parent_key, isbn=isbn)
book.put()
...
class Book(ndb.Model):
isbn = ndb.StringProperty()
@classmethod
def query_books(cls, ancestor_key):
return cls.query(ancestor=ancestor_key)
对于 emberjs 客户端,我使用 RESTAdapter:
window.Books = Ember.Application.create();
Books.ApplicationAdapter = DS.RESTAdapter.extend();
我的 emberjs 图书模型定义如下:
Books.Book = DS.Model.extend({
isbn: DS.attr('string'),
});
我添加了以下书籍控制器:
Books.BookController = Ember.ObjectController.extend({
actions: {
removeBook: function() {
var book = this.get('model');
book.deleteRecord();
book.save();
}
}
});
Books.BooksController = Ember.ArrayController.extend({
actions: {
createBook: function() {
// get book isbn
var isbn = this.get('newIsbn');
if(!isbn.trim()) { return; }
// create new book model
var book = this.store.createRecord('book', {
isbn: isbn,
});
// clear the 'new book' text field
this.set('newIsbn', '');
// Save model
book.save();
}
}
});
最后是以下路线:
Books.Router.map(function () {
this.resource('books', { path: '/' });
});
Books.BooksRoute = Ember.Route.extend({
model: function() {
return this.store.find('book');
}
});
使用 FixedAdapter 添加和删除书籍有效,然后我切换到 RESTAdapter。
GET 方法有效。Emberjs 自动调用 GET 方法,成功获取到 index.hbs 模板中显示的 JSON 格式的书籍列表。
但是,emberjs 以我没想到的方式调用 POST 方法。ember 似乎发送了一个空的 POST,而没有将 isbn 添加为 POST 数据。因为当我从cherrypy POST 函数中删除isbn 关键字参数时,该函数会被调用。不过,我需要 isbn 来创建 book 对象。
我可能在这里忘记了一些明显的东西,但我不知道是什么。有谁知道我忘记了什么或做错了什么?谢谢。
巴斯蒂安