List ToDo API
In this chapter we will create endpoint /api/todos
to list all created Task
in our database.
Write the Test
First let's create test at tests/features/task/list_task_api_test.py
from http import HTTPStatus
from tests.base import BaseAPITestCase
from app.tasks.models.task import Task
from app.factory import db
class ListTaskAPITest(BaseAPITestCase):
def test_list_task_api(self):
endpoint = "/api/todos"
task_1 = Task(name="Finish Homework")
task_2 = Task(name="Clean up closet")
db.session.add_all([task_1, task_2])
db.session.commit()
resp = self.client.get(endpoint)
self.assertEqual(resp.status_code, HTTPStatus.OK)
resp_json = resp.json or dict()
data = resp_json["data"]
self.assertEqual(data[0]["name"], "Finish Homework")
self.assertEqual(data[1]["name"], "Clean up closet")
Task.query.delete()
db.session.commit()
Invoke test by running command
$ bin/test tests/features/task/list_task_api_test.py
It will return error
F
======================================================================
FAIL: test_list_task_api (tests.features.task.list_task_api_test.ListTaskAPITest)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/usr/src/app/tests/features/task/list_task_api_test.py", line 17, in test_list_task_api
self.assertEqual(resp.status_code, HTTPStatus.OK)
AssertionError: 405 != <HTTPStatus.OK: 200>
----------------------------------------------------------------------
Ran 1 test in 0.019s
FAILED (failures=1)
It raise error 405 (HTTP Method Not Allowed) since we not implement our routes yet.
Let's implement our routes at file app/tasks/views/list_task_api.py
from http import HTTPStatus
from flask import jsonify
from flask.typing import ResponseReturnValue
from flask.views import View
from app.factory import db
from app.tasks.models.task import Task
from app.tasks.schemas.task_schema import TaskSchema
class ListTaskAPI(View):
def dispatch_request(self) -> ResponseReturnValue:
tasks_schema = TaskSchema(many=True)
tasks = Task.query.all()
resp = {
"data": tasks_schema.dump(tasks)
}
return jsonify(resp), HTTPStatus.OK
Then register it app/routes/api.py
from app.http.route import Route
from app.tasks.views.list_task_api import ListTaskAPI
from app.tasks.views.create_task_api import CreateTaskAPI
from app.views.main_api import MainView
api_routes = [
Route.get("/", MainView),
Route.group("/api", routes=[
Route.post("/todos", view=CreateTaskAPI),
Route.get("/todos", view=ListTaskAPI),
]),
]
Let's re run the test
$ bin/test tests/features/task/list_task_api_test.py
It should passed
.
----------------------------------------------------------------------
Ran 1 test in 0.031s
OK
Re-run all test to ensure our new feature not breaking existing feature
$ bin/test discover -s tests -p '*_test.py'
It should pass all tests
.....
----------------------------------------------------------------------
Ran 5 tests in 0.084s
OK
Your final project structure should be look like this
flask-todo
├── app
│ ├── config.py
│ ├── factory.py
│ ├── http
│ │ ├── __init__.py
│ │ └── route.py
│ ├── __init__.py
│ ├── routes
│ │ ├── api.py
│ │ └── __init__.py
│ ├── tasks
│ │ ├── __init__.py
│ │ ├── models
│ │ │ ├── __init__.py
│ │ │ └── task.py
│ │ ├── schemas
│ │ │ ├── __init__.py
│ │ │ └── task_schema.py
│ │ └── views
│ │ ├── create_task_api.py
│ │ ├── __init__.py
│ │ └── list_task_api.py
│ └── views
│ ├── __init__.py
│ └── main_api.py
├── bin
│ └── test
├── db
│ ├── create.sql
│ └── Dockerfile
├── docker-compose.yml
├── Dockerfile
├── .dockerignore
├── .env.dev
├── .gitignore
├── migrations
│ ├── alembic.ini
│ ├── env.py
│ ├── README
│ ├── script.py.mako
│ └── versions
│ └── 213adaf34061_create_tasks_tables.py
├── requirements.txt
├── serve.py
└── tests
├── base.py
├── features
│ ├── __init__.py
│ └── task
│ ├── create_task_api_test.py
│ ├── __init__.py
│ └── list_task_api_test.py
├── __init__.py
└── unit
├── __init__.py
└── task
├── __init__.py
└── task_model_test.py
17 directories, 41 files
We can commit our works before continuing to next chapter.
(venv)$ git add .
(venv)$ git commit -m "Create ListTaskAPI endpoint"