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

jrc*_*jrc 5 eve

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

我想使用1)一个HTTP请求来创建一个列表(可能带有初始项),2)一个HTTP请求添加一个项(一个常用操作),3)一个HTTP请求来获取列表(包括所有儿童用品).换一种说法:

1)POST /lists身体

{
  "title": "My List",
  "items": [{
      "name": "Alice"
    },
    {
      "name": "Bob"
    }]
}
Run Code Online (Sandbox Code Playgroud)

2)POST /lists/555555555555555555555555/items身体

{
   "name": "Carol"
}
Run Code Online (Sandbox Code Playgroud)

3) GET /lists/555555555555555555555555

{
  "_id": "555555555555555555555555",
  "title": "My List",
  "items": [{
      "_id": "aaaaaaaaaaaaaaaaaaaaaaaa",
      "name": "Alice"
    },
    {
      "_id": "bbbbbbbbbbbbbbbbbbbbbbbb",
      "name": "Bob"
    },
    {
      "_id": "cccccccccccccccccccccccc",
      "name": "Carol"
    }]
}
Run Code Online (Sandbox Code Playgroud)

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

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

jrc*_*jrc 3

我弄清楚了如何实现(2)和(3),使用数据库事件挂钩将嵌入的子文档注入到父列表中,然后再将其返回给客户端(并且在删除父文档时也删除子文档)。这有效并支持单个列表项上的预期 REST 使用。然而,它会导致两个数据库查询。

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

欢迎任何进一步的改进/建议。如果有一种更简单的方法来完成此任务(关键字:与嵌入文档的一对多关系),那就太好了。

设置.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
}
Run Code Online (Sandbox Code Playgroud)

主要.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
Run Code Online (Sandbox Code Playgroud)

用法

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
Run Code Online (Sandbox Code Playgroud)