How to set up a REST API in Flask in 5 steps

This small tutorial was built on top of my previous code sample that configures a simple Flask app with testing:

How to add basic unit test to a Python Flask app using Pytest
Carlos Villavicencio ・ May 18 ‘…


This content originally appeared on DEV Community and was authored by Carlos Villavicencio

This small tutorial was built on top of my previous code sample that configures a simple Flask app with testing:

There are many ways to build REST APIs, the most common is to have a Django app with DRF. Other people are trying FastAPI (I need to take a closer look at it, maybe in a future post).

But if you are using a Flask based app, I recently tried Flask-RESTX library which includes some great features:

  • Swagger documentation (Heck yes!)
  • Response marshalling
  • Request parsing
  • Error handling, logging and blueprint support. Neat Flask integration.

In this demo, I'll show you how to set up a quick REST API, with Swagger documentation, request parsing and simple response formatting.

Let's start by initializing the blueprint and defining the api object in a new module. I named this one as api.py.

blueprint = Blueprint("api", __name__, url_prefix="/api/v1")

api = Api(
    blueprint,
    version="1.0",
    title="Mini REST API",
    description="A mini REST API",
)
ns = api.namespace("items", description="Item operations")
api.add_namespace(ns)

Flask-RESTX support Flask Blueprint and they are really simple to implement.

My application is served at http://localhost:5000 but my API base URL will be http://localhost:5000/api/v1. This is also the page where you can find the Swagger docs.

Swagger landing page sample

Next, let's write the base models. My sample API will manage Items and Details objects, so I need to write the models that will be in charge of presenting them in the API standard response.

detail_model = api.model("Detail", {"id": fields.Integer, "name": fields.String})
item_model = api.model(
    "Item",
    {
        "id": fields.Integer,
        "name": fields.String,
        "details": fields.List(fields.Nested(detail_model)),
    },
)

The idea of writing models is to use Flask-RESTX response marshalling, so no matter if our objects scale, the response will always be as we document it on our models. Flask-RESTX includes a lot of tools for this such as renaming attributes, complex, custom, and nested fields, and more.

The final set up step is to write the request parser.

item_parser = api.parser()
item_parser.add_argument("id", type=int, location="form")
item_parser.add_argument("name", type=str, location="form")

detail_parser = api.parser()
detail_parser.add_argument("id", type=int, location="form")
detail_parser.add_argument("name", type=str, location="form")

In a similar way as before, we make use of Flask-RESTX request parser to read and validate values that we expect to receive in our endpoints. In this case I plan to implement two object APIs that will append elements to our database objects. (Our database is a simple in-memory object 😅)

memory_object = [
    {
        "id": 1,
        "name": "Item 1",
        "details": [
            {"id": 1, "name": "Detail 1"},
            {"id": 2, "name": "Detail 2"},
        ],
    }
]

Now it's time to implement our APIs. The first API I want to build is the one that manages the items. I will call this ItemApi and the route will be / which means the root of the namespace items.

@ns.route("/")
class ItemsApi(Resource):
    """
    API for handling the Item list resource
    """

    @api.response(HTTPStatus.OK.value, "Get the item list")
    @api.marshal_list_with(item_model)
    def get(self) -> list[Item]:
        """
        Returns the memory object
        """
        return memory_object

    @api.response(HTTPStatus.OK.value, "Object added")
    @api.expect(item_parser)
    def post(self) -> None:
        """
        Simple append something to the memory object
        """
        args = item_parser.parse_args()
        memory_object.append(args)

This will enable two endpoints:

Endpoint Method Parameters Returns
/api/v1/items/ GET None list of item_model
/api/v1/items/ POST As defined on item_parser None

All decorators are provided by Flask-RESTX. HTTPStatus class is provided by the http module. Pretty simple huh?, let's build the second one.

This one will manage a single item resource. So, to get its data and add details we need the following implementation:

@ns.route("/<int:item_id>")
class ItemApi(Resource):
    """
    API for handling the single Item resource
    """

    @api.response(HTTPStatus.OK.value, "Get the item list")
    @api.response(HTTPStatus.BAD_REQUEST.value, "Item not found")
    @api.marshal_with(item_model)
    def get(self, item_id: int) -> Item:
        """
        Returns the memory object
        """
        try:
            return self._lookup(item_id)
        except StopIteration:
            return api.abort(HTTPStatus.BAD_REQUEST.value, "Item not found")

    def _lookup(self, item_id):
        return next(
            (item for item in memory_object if item["id"] == item_id),
        )

    @api.response(HTTPStatus.NO_CONTENT.value, "Object added")
    @api.response(HTTPStatus.BAD_REQUEST.value, "Item not found")
    @api.expect(detail_parser)
    def post(self, item_id: int) -> None:
        """
        Simple append details to the memory object
        """
        args = item_parser.parse_args()
        try:
            if item := self._lookup(item_id):
                item["details"].append(args)
            return None
        except StopIteration:
            return api.abort(HTTPStatus.BAD_REQUEST.value, "Item not found")

This will enable two more endpoints:

Endpoint Method Parameters Returns
/api/v1/items/<item_id> GET None a single item_model resource.
/api/v1/items/<item_id> POST As defined on detail_parser None

To wrap up our application, you only need to import the module at app.py and register the Blueprint.

from api import blueprint

app = Flask(__name__)  # This line already exists
app.register_blueprint(blueprint)

You can fork and play with this example using this repo:

Mini example of Flask and Flask-RESTX

Actions Workflow

This is a examle repository for my article.

Setup

Create and activate the virtual environment

virtualenv venv
source venv/bin/activate

Run the server

FLASK_ENV=development flask run

Check out the Swagger documentation and playground at

http://localhost:5000/api/v1/

Run the tests

python -m pytest

The server will be up on http://localhost:5000 and the API landing page will be available on http://127.0.0.1:5000/api/v1/.

Requirements

Python >= 3.6

License

MIT

I also added some unit tests and type annotations for your delight 😉.

Any feedback or suggestions are welcome and I'll be happy to answer any question you may have.


This content originally appeared on DEV Community and was authored by Carlos Villavicencio


Print Share Comment Cite Upload Translate Updates
APA

Carlos Villavicencio | Sciencx (2021-11-05T22:07:25+00:00) How to set up a REST API in Flask in 5 steps. Retrieved from https://www.scien.cx/2021/11/05/how-to-set-up-a-rest-api-in-flask-in-5-steps/

MLA
" » How to set up a REST API in Flask in 5 steps." Carlos Villavicencio | Sciencx - Friday November 5, 2021, https://www.scien.cx/2021/11/05/how-to-set-up-a-rest-api-in-flask-in-5-steps/
HARVARD
Carlos Villavicencio | Sciencx Friday November 5, 2021 » How to set up a REST API in Flask in 5 steps., viewed ,<https://www.scien.cx/2021/11/05/how-to-set-up-a-rest-api-in-flask-in-5-steps/>
VANCOUVER
Carlos Villavicencio | Sciencx - » How to set up a REST API in Flask in 5 steps. [Internet]. [Accessed ]. Available from: https://www.scien.cx/2021/11/05/how-to-set-up-a-rest-api-in-flask-in-5-steps/
CHICAGO
" » How to set up a REST API in Flask in 5 steps." Carlos Villavicencio | Sciencx - Accessed . https://www.scien.cx/2021/11/05/how-to-set-up-a-rest-api-in-flask-in-5-steps/
IEEE
" » How to set up a REST API in Flask in 5 steps." Carlos Villavicencio | Sciencx [Online]. Available: https://www.scien.cx/2021/11/05/how-to-set-up-a-rest-api-in-flask-in-5-steps/. [Accessed: ]
rf:citation
» How to set up a REST API in Flask in 5 steps | Carlos Villavicencio | Sciencx | https://www.scien.cx/2021/11/05/how-to-set-up-a-rest-api-in-flask-in-5-steps/ |

Please log in to upload a file.




There are no updates yet.
Click the Upload button above to add an update.

You must be logged in to translate posts. Please log in or register.