CherryPy从emberjs RESTAdapter接收空POST

时间:2013-10-21 12:44:06

标签: ember.js cherrypy

我正在探索使用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方法并成功获取以jSON格式显示在index.hbs模板中的书籍列表。

然而,emberjs以我没想到的方式调用POST方法。似乎ember发送了一个空POST,没有将isbn添加为POST数据。因为当我从cherrypy POST函数中删除isbn关键字参数时,函数会被调用。我需要isbn来创建书籍对象。

我可能忘记了一些明显的东西,但我无法弄清楚是什么。有谁知道我忘了或做错了什么?感谢。

1 个答案:

答案 0 :(得分:1)

为了保存新记录,Ember发送保存在帖子正文中的对象的json表示...

在你的情况下sholud是

book:{isbn:[the isbn value]}

所以没有isbn参数

你可以在帖子功能上测试吗

def POST(self):

    # get the current user
    user = users.get_current_user()
    cl = cherrypy.request.headers['Content-Length']
    rawbody = cherrypy.request.body.read(int(cl))
    body = simplejson.loads(rawbody)
    bookFromPost = body.book
    # create book and save in data storage
    parent_key = ndb.Key('Library', user.user_id())
    book = Book(parent=parent_key, isbn=bookFromPost.isbn)
    book.put()

您应该返回一个201创建的HTTP代码,其中包含具有指定ID

的书籍的json表示
book:{id:[the new id],isbn:[the isbn value]}