Now, we can run the api/run.py
script that launches Flask's development. Execute the following command in the api folder.
python run.py
The following lines show the output after we execute the preceding command. The development server is listening at port 5000
.
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit) * Restarting with stat * Debugger is active! * Debugger pin code: 198-040-402
Now, we will use the HTTPie command or its curl equivalents to compose and send HTTP requests to the API. We will use JSON for the requests that require additional data. Remember that you can perform the same tasks with your favorite GUI-based tool.
First, we will compose and send HTTP requests to create two message categories:
http POST :5000/api/categories/ name='Information' http POST :5000/api/categories/ name='Warning'
The following are the equivalent curl
commands:
curl -iX POST -H "Content-Type: application/json" -d '{"name":"Information"}' :5000/api/categories/ curl -iX POST -H "Content-Type: application/json" -d '{"name":"Warning"}' :5000/api/categories/
The preceding commands will compose and send two POST
HTTP requests with the specified JSON key-value pair. The requests specify /api/categories/
, and therefore, they will match the '/api'url_prefix
for the api_bp
blueprint. Then, the request will match the '/categories/'
URL route for the CategoryList
resource and run the CategoryList.post
method. The method doesn't receive arguments because the URL route doesn't include any parameters. As the HTTP verb for the request is POST
, Flask calls the post
method. If the two new Category
instances were successfully persisted in the database, the two calls will return an HTTP 201 Created
status code and the recently persisted Category
serialized to JSON in the response body. The following lines show an example response for the two HTTP requests, with the new Category
objects in the JSON responses.
Note that the responses include the URL, url
, for the created categories. The messages
array is empty in both cases because there aren't messages related to each new category yet:
HTTP/1.0 201 CREATED Content-Length: 116 Content-Type: application/json Date: Mon, 08 Aug 2016 05:26:58 GMT Server: Werkzeug/0.11.10 Python/3.5.1 { "id": 1, "messages": [], "name": "Information", "url": "http://localhost:5000/api/categories/1" } HTTP/1.0 201 CREATED Content-Length: 112 Content-Type: application/json Date: Mon, 08 Aug 2016 05:27:05 GMT Server: Werkzeug/0.11.10 Python/3.5.1 { "id": 2, "messages": [], "name": "Warning", "url": "http://localhost:5000/api/categories/2" }
Now, we will compose and send HTTP requests to create two messages that belong to the first message category we recently created: Information
. We will specify the category
key with the name of the desired message category. The database table that persists the Message
model will save the value of the primary key of the related Category
whose name value matches the one we provide:
http POST :5000/api/messages/ message='Checking temperature sensor' duration=5 category="Information" http POST :5000/api/messages/ message='Checking light sensor' duration=8 category="Information"
The following are the equivalent curl
commands:
curl -iX POST -H "Content-Type: application/json" -d '{"message":" Checking temperature sensor", "category":"Information"}' :5000/api/messages/ curl -iX POST -H "Content-Type: application/json" -d '{"message":" Checking light sensor", "category":"Information"}' :5000/api/messages/
The first command will compose and send the following HTTP request: POST http://localhost:5000/api/messages/
with the following JSON key-value pairs:
{ "message": "Checking temperature sensor", "category": "Information" }
The second command will compose and send the same HTTP request with the following JSON key-value pairs:
{ "message": "Checking light sensor", "category": "Information" }
The requests specify /api/categories/
, and therefore, they will match the '/api'url_prefix
for the api_bp
blueprint. Then, the request will match the '/messages/'
URL route for the MessageList
resource and run the MessageList.post
method. The method doesn't receive arguments because the URL route doesn't include any parameters. As the HTTP verb for the request is POST
, Flask calls the post
method. The the MessageSchema.process_category
method will process the data for the category and the MessageListResource.post
method will retrieve the Category
that matches the specified category name from the database, to use it as the related category for the new message. If the two new Message
instances were successfully persisted in the database, the two calls will return an HTTP 201 Created
status code and the recently persisted Message
serialized to JSON in the response body. The following lines show an example response for the two HTTP requests, with the new Message
objects in the JSON responses. Note that the responses include the URL, url
, for the created messages. In addition, the response includes the id
, name
, and url
for the related category.
HTTP/1.0 201 CREATED Content-Length: 369 Content-Type: application/json Date: Mon, 08 Aug 2016 15:18:43 GMT Server: Werkzeug/0.11.10 Python/3.5.1 { "category": { "id": 1, "name": "Information", "url": "http://localhost:5000/api/categories/1" }, "creation_date": "2016-08-08T12:18:43.260474+00:00", "duration": 5, "id": 1, "message": "Checking temperature sensor", "printed_once": false, "printed_times": 0, "url": "http://localhost:5000/api/messages/1" } HTTP/1.0 201 CREATED Content-Length: 363 Content-Type: application/json Date: Mon, 08 Aug 2016 15:27:30 GMT Server: Werkzeug/0.11.10 Python/3.5.1 { "category": { "id": 1, "name": "Information", "url": "http://localhost:5000/api/categories/1" }, "creation_date": "2016-08-08T12:27:30.124511+00:00", "duration": 8, "id": 2, "message": "Checking light sensor", "printed_once": false, "printed_times": 0, "url": "http://localhost:5000/api/messages/2" }
We can run the preceding commands to check the contents of the tables that the migrations created in the PostgreSQL database. We will notice that the category_id
column for the message
table saves the value of the primary key of the related row in the category
table. The MessageSchema
class uses a fields.Nested
instance to render the id
, url
and name fields for the related Category
. The following screenshot shows the contents for the category
and the message
table in a PostgreSQL database after running the HTTP requests:
Now, we will compose and send an HTTP request to retrieve the category that contains two messages, that is the category resource whose id or primary key is equal to 1
. Don't forget to replace 1
with the primary key value of the category whose name is equal to 'Information'
in your configuration:
http :5000/api/categories/1
The following is the equivalent curl command:
curl -iX GET :5000/api/categories/1
The preceding command will compose and send a GET
HTTP request. The request has a number after /api/categories/
, and therefore, it will match '/categories/<int:id>'
and run the CategoryResource.get
method, that is, the get
method for the CategoryResource
class. If a Category
instance with the specified id exists in the database, the call to the method will will return an HTTP200 OK
status code and the Category
instance serialized to JSON in the response body. The CategorySchema
class uses a fields.Nested
instance to render all the fields for all the messages related to the category excepting the category field. The following lines show a sample response:
HTTP/1.0 200 OK Content-Length: 1078 Content-Type: application/json Date: Mon, 08 Aug 2016 16:09:10 GMT Server: Werkzeug/0.11.10 Python/3.5.1 { "id": 1, "messages": [ { "category": { "id": 1, "name": "Information", "url": "http://localhost:5000/api/categories/1" }, "creation_date": "2016-08-08T12:27:30.124511+00:00", "duration": 8, "id": 2, "message": "Checking light sensor", "printed_once": false, "printed_times": 0, "url": "http://localhost:5000/api/messages/2" }, { "category": { "id": 1, "name": "Information", "url": "http://localhost:5000/api/categories/1" }, "creation_date": "2016-08-08T12:18:43.260474+00:00", "duration": 5, "id": 1, "message": "Checking temperature sensor", "printed_once": false, "printed_times": 0, "url": "http://localhost:5000/api/messages/1" } ], "name": "Information", "url": "http://localhost:5000/api/categories/1" }
Now, we will compose and send a POST
HTTP request to create a message related to a category name that doesn't exist: 'Error'
:
http POST :5000/api/messages/ message='Temperature sensor error' duration=10 category="Error"
The following are the equivalent curl commands:
curl -iX POST -H "Content-Type: application/json" -d '{"message":" Temperature sensor error", "category":"Error"}' :5000/api/messages/
The CategoryListResource.post
method won't be able to retrieve a Category
instance whose name
is equal to the specified value, and therefore, the method will create a new Category
, save it and use it as the related category for the new message. The following lines show an example response for the HTTP request, with the new Message
object in the JSON responses and the details for the new Category
object related to the message:
HTTP/1.0 201 CREATED Content-Length: 361 Content-Type: application/json Date: Mon, 08 Aug 2016 17:20:22 GMT Server: Werkzeug/0.11.10 Python/3.5.1 { "category": { "id": 3, "name": "Error", "url": "http://localhost:5000/api/categories/3" }, "creation_date": "2016-08-08T14:20:22.103752+00:00", "duration": 10, "id": 3, "message": "Temperature sensor error", "printed_once": false, "printed_times": 0, "url": "http://localhost:5000/api/messages/3" }
We can run the commands explained earlier to check the contents of the tables that the migrations created in the PostgreSQL database. We will notice that we have a new row in the category table with the recently added category when we created a new message. The following screenshot shows the contents for the category
and message
tables in a PostgreSQL database after running the HTTP requests:
3.148.103.210