【发布时间】:2015-12-06 14:00:31
【问题描述】:
我通过在我的 eve-API 上执行 POST 请求将新数据添加到我的数据库中。 由于需要从 Python 端添加一些数据,我想我可以使用 pre-request event hook 添加这些数据。
那么有没有办法在将数据插入数据库之前使用预请求挂钩来修改 POST 请求中包含的数据?我已经了解如何实现这样的钩子,但不知道如何在插入数据库之前修改数据。
【问题讨论】:
我通过在我的 eve-API 上执行 POST 请求将新数据添加到我的数据库中。 由于需要从 Python 端添加一些数据,我想我可以使用 pre-request event hook 添加这些数据。
那么有没有办法在将数据插入数据库之前使用预请求挂钩来修改 POST 请求中包含的数据?我已经了解如何实现这样的钩子,但不知道如何在插入数据库之前修改数据。
【问题讨论】:
您可能想查看database hooks,特别是insert hooks:
当 POST 请求到达 API 并且新项目即将存储在数据库中时,会触发这些通风口:
on_insert用于每个资源端点。
on_insert_<resource_name>用于特定资源端点。回调函数可以挂钩这些事件,以任意添加新字段或编辑现有字段。
在下面的代码中:
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 插入。旁注,最终您可以将多个回调挂钩到同一事件(因此使用加法运算符+=)。
【讨论】:
required_field 错误?
required 规则,或者更好地添加对不同规则的支持(查看文档中的“自定义验证”)。
python server.py 运行服务器时,钩子可以工作,但是当使用 WSGI 钩子运行应用程序时,它不起作用,并且控制台中没有显示错误。
就我而言,如果给定的属性在数据中,我想复制文档。
我必须使用 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
【讨论】: