Reputation: 8593
I am adding new data into my Database by doing a POST-request on my eve-API. Since there need to be added some data from the Python side I thought I could add these data by using a pre-request event hook.
So is there a way to modify the data contained in the POST-request using a pre-request hook before inserting the data into the database? I already understood how to implement such a hook but do not have any clue about how to modify data before inserting to DB.
Upvotes: 4
Views: 3460
Reputation: 31
Just to complement the answer of @Gustavo (I cannot leave a comment in his answer). You can update the request._cached_json
property without serializing your data.
Using his example:
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
Upvotes: 0
Reputation: 126
In my case I wanted to duplicate documents if a given property is in data.
I have to use pre_POST event hook to do that.
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')
First, I tried to replace request.data but it does not work. Doing some search on code I figured out the _cached_data property. Then it works.
Upvotes: 1
Reputation: 6576
You probably want to look at 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.
In the code below:
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()
Every time a POST hits the API the before_insert
function is invoked. The function updates field1
for every document. Since this callback is invoked before the payload is sent to the database, changes will be persisted to the database.
An interesting alternative would be:
def before_insert(resource_name, documents):
for document in documents:
document['field'] = 'value'
app = Eve()
app.on_insert_myresource += before_insert
app.run()
In the callback we are not testing the endpoint name anymore. This is because we hooked our callback to the on_insert_myresoure
event so the function will only be called when POST request are performed on the myresource
endpoint. Better separation of concerns, code is simpler and also, improved performance since the callback is not going to be hit an all API inserts. Side note, eventually you can hook multiple callbacks to the same event (hence the use of the addition operator +=
).
Upvotes: 5