Build a Python REST API in 5 Minutes
2. Creating the Characters Resource.
Now that we’ve got our application set up we can start creating our Characters APIs. We will add endpoints that allow clients to fetch a list of characters, create new characters, find a character by and and update and delete characters.
Before we can create our new APIs we need to create the Character model and CharacterMapper.
$ touch star_wars/models/character.py
$ touch star_wars/apis/v1/characters.py
$ touch star_wars/apis/v1/mappers/character.py
We’ll start with a very simple Character object that has a name.
Now import the model in the models/__init__.py
Create a migration for the new model.
$docker-compose run --rm api flask db revision "character model"
INFO [alembic.runtime.migration] Context impl SQLiteImpl.
INFO [alembic.runtime.migration] Will assume non-transactional DDL.
INFO [alembic.autogenerate.compare] Detected added table 'character'
Generating /opt/code/star_wars/migrations/d7d80c02d806_character_model.py ... done
# Now apply the migration to create the table
$docker-compose run --rm api flask db upgrade
Add the Character mapper to the file we created earlier. star_wars/apis/v1/mappers/character.py
The Mapper is responsible for serializing and marshaling our APIS data. You can read more about Kim here
Now import the mapper to the mapper/__init__.py
module
Great! Now we have our database model and a way to serialize it, let’s create an endpoint that allows our API clients to get a list of characters. Add the following code to the api/v1/characters.py
file we created.
Now we need to register our new Resource with the Arrested API object. Open up apis/v1/__init__.py
module and import the characters_resource. Then register the resource against the v1 API object. Also specify the defer=True
to instruct Arrested to defer registering the routes with Flask until the API object is initialised.
Let’s give our new Endpoint a test run. Make sure the Docker container is running and then use the curl command provided to make a GET request to the characters resource.
$ docker-compose up api
$ curl -u admin:secret localhost:8080/v1/characters | python -m json.tool
{
"payload": []
}
Awesome! We got a response but we’ve not got any character objects in our database yet. Now we need to add the ability to create new characters via our endpoint using the DBCreateMixin
Our characters.py module now looks like this
All we needed to do to support the creation of our Character object was mixin the DBCreateMixin
to our CharactersIndexEndpoint.
Arrested’s integration with SQLAlchemy and Kim handles validating the incoming data, converting our JSON input into a Character object and then persisting it to the database. Let’s go ahead and create a Character.
curl -u admin:secret -H "Content-Type: application/json" -d '{"name":"Darth Vader"}' -X POST localhost:8080/v1/characters | python -m json.tool
{
"payload": {
"created_at": "2017-11-22T08:18:26.044931",
"id": 1,
"name": "Darth Vader",
"updated_at": "2017-11-22T08:18:26.044958"
}
}
Darth Vader was successfully created. Now if we make the GET request we made earlier at our API we should see Darth Vader returned.
curl -u admin:secret localhost:8080/v1/characters | python -m json.tool
{
"payload": [
{
"created_at": "2017-11-22T08:18:26.044931",
"id": 1,
"name": "Darth Vader",
"updated_at": "2017-11-22T08:18:26.044958"
}
]
}
Now we need to set up an Endpoint that allows clients to fetch a Character using a resource ID.
We’ve added a new Endpoint CharacterObjectEndpoint
and registered it with the characters resource. The DBObjectMixin
will allow us to fetch a resource by ID, update a specific resource and delete a resource. Let’s try it out.
# Fetch a character with a resource id of 1curl -u admin:secret localhost:8080/v1/characters/1 | python -m json.tool
{
"payload": {
"created_at": "2017-11-22T08:18:26.044931",
"id": 1,
"name": "Darth Vader",
"updated_at": "2017-11-22T08:18:26.044958"
}
}
# Then we can update the characters name
curl -u admin:secret -H "Content-Type: application/json" -d '{"id": 1, "name":"Anakin Skywalker"}' -X PUT localhost:8080/v1/characters/1 | python -m json.tool
{
"payload": {
"created_at": "2017-11-22T08:18:26.044931",
"id": 1,
"name": "Anakin Skywalker",
"updated_at": "2017-11-22T08:18:26.044958"
}
}
# And finally delete a character
curl -u admin:secret -X DELETE localhost:8080/v1/characters/1