Note: this article is written by my colleague Keyur. We blog at the same place
Intro to RESTful APIs
RESTful APIs using JSON on the HTTP protocol is by far the most popular approach to creating web APIs.They enable developers to think in terms of resources with actions on those resourceslike CRUD (Create, Read, Update, Delete). However, there are upcoming APIs like GraphQL which is increasingly becoming popular with many applications.
In this tutorial, we are going to build a RESTful API to create, read, updateand delete the documents (which will contain User information) from a Mongo databaseusing Python and Flask framework.
Getting started
Here are the tools we’ll need to build our APIs:
- Python 2.7
- Postman Download here
- Mongo Database Documentation
- Robo 3T Download here
Creating your local environment
NOTE:While working with Python, we would recommend to use virtual environmentto keep all the project’s dependencies isolated from other projects.
conda create -n restfulapi python=2.7 anaconda # Create the environment
source activate restfulapi # Activate the environment
Install dependencies
pip install -r requirements.txt
Start the MongoDB server
If you’re using MacOS, you could use brew
to start the server.
brew services start mongodb
Collections in MongoDB
A collection is similar to a table in a traditional relational Db. We will createda Users collection tostore user details similar to a Users table in SQL.
Create Users
We will create an endpoint POST /api/v1/users
which takes in a JSON object consisting ofthe user details like name
, email
, phone
as JSON in the request body.We could also design the endpoint to take an array of users.
@app.route("/api/v1/users", methods=['POST'])
def create_user():
"""
Function to create new users.
"""
try:
# Create new users
body = ast.literal_eval(json.dumps(request.get_json()))
record_created = collection.insert(body)
body._id = record_created.inserted_id
# Prepare the response
return jsonify(body)
except:
# Something went wrong server side, so return Internal Server Error.
resp.status_code = 500
return resp
If this is a batch endpoint taking in an array of users, we could return the number of users created.On the other hand, a single user may return the entity id so the frontend can reference the newlycreated item.
Read Users
To fetch a list users which we just created, we will design an endpointGET /api/v1/users
and pass the search criteria as the query string parameters.
@app.route("/api/v1/users", methods=['GET'])
def fetch_users():
"""
Function to fetch the users.
"""
# Prepare the response
try:
# Call the function to get the query params
query_params = helper_module.parse_query_params(request.query_string)
key = query_params.keys()[0]
value = query_params.values()[0]
# Encode params
key, value = helper_module.encode_params(key, value)
# Fetch all the record(s)
records_fetched = collection.find({key: value})
if len(records_fetched) > 0:
# Prepare the response
resp = jsonify(records_fetched)
return resp
else:
# No records found, so we can return an empty list (Added for example)
return jsonify([])
except:
# Something went wrong server side, so return Internal Server Error.
resp.status_code = 500
return resp
We will return the user details if the matching document is found else wewould return an empty array.
Update Users
Now, we will design an endpoint POST /api/v1/users/<user_id>
to update the user details.
@app.route("/api/v1/users/<user_id>", methods=['POST'])
def update_user():
"""
Function to update the user.
"""
try:
# Update the user
body = ast.literal_eval(json.dumps(request.get_json()))
record_updated = collection.update_one({"_id": user_id}, body)
# Prepare the response
resp = jsonify(body)
except:
resp.status_code = 500
# Return the object
return resp
UPDATE Request:
Remove Users
Finally, we will design an endpoint DELETE /api/v1/users/<user_id>
to delete the userfrom the database.
@app.route("/api/v1/users/<user_id>", methods=['DELETE'])
def remove_user():
"""
Function to remove the user.
"""
try:
# Delete all the users matched
body = ast.literal_eval(json.dumps(request.get_json()))
record_deleted = collection.delete_one({ "_id" : user_id })
# Prepare the response
if result.deleted_count > 0
# We return 204 No Content to imply resource updated successfully without returning
# the deleted entity.
resp.status_code = 204
return resp
else:
# Entity not found, perhaps already deleted, return 404
resp.status_code = 404
return resp
except:
# Something went wrong server side, so return Internal Server Error.
resp.status_code = 500
return resp
We would specify the matching condition on which to delete the document in therequest body. For example, we would like to remove the document with id
is 3
Once the users are deleted, we would return the number of deleted users messageto the client.
Handling page not found request
We recommend to handle page not found request with informative message to the user.
@app.errorhandler(404)
def page_not_found(e):
"""Send message to user with notFound 404 status."""
# Message to the user
message = {
"message": "Message from the API",
"errors": [
{
"message": "This route is not currently supported. Please refer API documentation."
}
]
}
# Make the message looks good
resp = jsonify(message)
# Send OK response
resp.status_code = 404
# Return the object
return resp
If you would like to play around the data, you could also use Robo 3T mongo shell.
To see the RESTful API in action, you can git clone and run this example appfrom GitHub
In the next blog, we would learn about how to authorize and authenticate our APIs.If you’re curious to get started with GraphQL using Python - please refer to this blog. Meanwhile, if you have any questions, reach out to the Moesif Team
Top comments (0)