Python-Eve:使用预请求事件挂钩在插入数据库之前修改数据

Python-Eve: Use Pre-Request Event Hooks to modify data before inserting to DB

我在 API 前夕通过 POST 请求将新数据添加到我的数据库中。 由于需要从 Python 端添加一些数据,我想我可以使用 pre-request event hook.

添加这些数据

那么有没有办法在将数据插入数据库之前使用预请求挂钩修改POST-请求中包含的数据?我已经了解如何实现这样的钩子,但不知道如何在插入数据库之前修改数据。

你可能想看看 database hooks, specifically at insert hooks:

When a POST requests hits the API and new items are about to be stored in the database, these vents are fired:

on_insert for every resource endpoint.

on_insert_<resource_name> for the specific resource endpoint.

Callback functions could hook into these events to arbitrarily add new fields or edit existing ones.

在下面的代码中:

def before_insert(resource_name, documents):
    if resource_name == 'myresource':
        for document in documents:
            document['field'] = 'value'

app = Eve()
app.on_insert += before_insert

app.run()

每次 POST 命中 API 时,都会调用 before_insert 函数。该函数为每个文档更新 field1。由于此回调是在有效负载发送到数据库之前调用的,因此更改将持久保存到数据库中。

一个有趣的选择是:

def before_insert(resource_name, documents):
    for document in documents:
        document['field'] = 'value'

app = Eve()
app.on_insert_myresource += before_insert

app.run()

在回调中我们不再测试端点名称。这是因为我们将回调挂钩到 on_insert_myresoure 事件,因此只有在 myresource 端点上执行 POST 请求时才会调用该函数。关注点分离更好,代码更简单,性能也得到提高,因为回调不会被 all API 插入。旁注,最终您可以将多个回调挂接到同一事件(因此使用加法运算符 +=)。

在我的例子中,如果给定的 属性 在数据中,我想复制文档。

我必须使用 pre_POST 事件挂钩来做到这一点。

def pre_notifications(request):
    data = json.loads(request.get_data())
    if 'payload' in data and 'condition' in data:
        notification = data['payload']
        documents = []
        users = app.data.pymongo().db.users.find()
        for user in users:
            copy_notification = copy(notification)
            copy_notification['user_email'] = user['user_email']
            documents.append(copy_notification)
        request._cached_data = json.dumps(documents).encode('utf-8')

首先,我尝试替换 request.data 但它不起作用。通过对代码进行一些搜索,我找到了 _cached_data 属性。然后就可以了。

只是为了补充@Gustavo 的回答(我不能在他的回答中发表评论)。您可以在不序列化数据的情况下更新 request._cached_json 属性。

以他为例:

def pre_notifications(request):
    data = json.loads(request.get_data())
    if 'payload' in data and 'condition' in data:
        notification = data['payload']
        documents = []
        users = app.data.pymongo().db.users.find()
        for user in users:
            copy_notification = copy(notification)
            copy_notification['user_email'] = user['user_email']
            documents.append(copy_notification)
        request._cached_json = documents