如何实现可追加的嵌入对象列表

时间:2017-01-27 13:47:06

标签: eve

我正在尝试使用Eve为简单的项目列表提供RESTful API。

我想使用1)一个HTTP请求来创建一个列表(可能带有初始项),2)一个HTTP请求添加一个项(一个常见的操作),3)一个HTTP请求来获取列表(包括所有子项)。换句话说:

1)POST /lists与身体

{
  "title": "My List",
  "items": [{
      "name": "Alice"
    },
    {
      "name": "Bob"
    }]
}

2)POST /lists/555555555555555555555555/items与身体

{
   "name": "Carol"
}

3)GET /lists/555555555555555555555555

{
  "_id": "555555555555555555555555",
  "title": "My List",
  "items": [{
      "_id": "aaaaaaaaaaaaaaaaaaaaaaaa",
      "name": "Alice"
    },
    {
      "_id": "bbbbbbbbbbbbbbbbbbbbbbbb",
      "name": "Bob"
    },
    {
      "_id": "cccccccccccccccccccccccc",
      "name": "Carol"
    }]
}

我还没弄明白如何用Eve做这件事。我可以(1)使用嵌入的dicts列表,但是我不能做(2) - 我必须POST一个项目,然后PATCH列表(?)。我可以做(2)使用子资源,但我不能做(1)("value '{'name': 'Alice'}' cannot be converted to a ObjectId")。或者我错过了什么?

如果不能完成所有这三项,至少可以(2)和(3)?

1 个答案:

答案 0 :(得分:3)

我想出了如何实现(2)和(3),使用数据库事件挂钩将嵌入的子文档注入父列表,然后将其返回给客户端(并且还删除父项时的子项)被删除)。这适用于并支持单个列表项上的预期REST使用。但是,它会产生两个数据库查询。

我怀疑(1)也可以使用事件挂钩实现,但现在就足够了。

欢迎任何进一步的改进/建议。如果有更简单的方法可以实现这一目标(关键字:One-to-Many Relationships with Embedded Documents)。

settings.py:

RESOURCE_METHODS = ['GET', 'POST', 'DELETE']
ITEM_METHODS = ['GET', 'PUT', 'PATCH', 'DELETE']

lists = {
    'schema': {
        'title': {
            'type': 'string'
        }
    }
}

items = {
    'url': 'lists/<regex("[a-f0-9]{24}"):list_id>/items',
    'schema': {
        'name': {'type': 'string',
                 'required': True
                 },
        'list_id': {
            'type': 'objectid',
            'required': True,
            'data_relation': {
                'resource': 'lists',
                'field': '_id'
            }
        }
    }
}

DOMAIN = {
    'lists': lists,
    'items': items
}

main.py:

from bson.objectid import ObjectId

def before_returning_lists(response):
    list_id = response['_id']
    response['items'] = list(db.items.find({'list_id': ObjectId(list_id)}))

def after_deleting_lists(item):
    list_id = item['_id']
    db.items.delete_many({'list_id': ObjectId(list_id)})

app.on_fetched_item_lists += after_fetching_lists
app.on_deleted_item_lists += after_deleting_lists

用法

curl -X POST http://127.0.0.1:5000/lists -d title="My List"

# (2)
curl -X POST http://127.0.0.1:5000/lists/5895fdb5a663e2dcad9e7647/items -d 'name=Alice'
curl -X POST http://127.0.0.1:5000/lists/5895fdb5a663e2dcad9e7647/items -d 'name=Bob'
curl -X POST http://127.0.0.1:5000/lists/5895fdb5a663e2dcad9e7647/items -d 'name=Carol'

# (3)
curl -X GET http://127.0.0.1:5000/lists/5895fdb5a663e2dcad9e7647