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
我在 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