- Lab
- Core Tech

Guided: Building a RESTful API with Flask
Unlock the power of Flask and learn to build a robust RESTful API in this hands-on Code Lab. You’ll implement CRUD operations for a user management system while mastering JSON data handling, request validation with Marshmallow, and returning appropriate HTTP status codes. Gain practical experience in designing, validating, and testing API endpoints, ensuring your APIs are both reliable and scalable. Whether you’re new to Flask or looking to deepen your API development expertise, this Code Lab provides the perfect blend of theory and real-world application to level up your skills.

Path Info
Table of Contents
-
Challenge
Set Up the Project
User Management API
In this lab, you'll build an User Management API using Flask, SQLite, and Marshmallow. This project focuses on implementing a RESTful API for managing users, complete with input validation and database integration. You'll learn to handle common Create, Read, Update, and Delete (CRUD) operations while leveraging Marshmallow for schema validation to ensure your data is valid.
What You'll Build
The User Management API will allow clients to:
- Create Users: Add new users with validation for required fields like
username
,email
, andpassword
. - Retrieve Users: Fetch a list of all users of retrieve a single user by ID.
- Update Users: Modify user details, such as their email or status.
- Delete Users: Remove users from the system. When working in your local environment, you would first need to install several dependencies for your project. Due to limitations in this environment, these are already installed to your instance. Here are a list of the dependencies:
flask
: This is the web framework you'll use to build the API.flask-sqlalchemy
: This allows your framework to "talk" SQL and interact with relational databases. For this project, you'll use it to work with SQLite, a lightweight, file-based database.flask-marshmallow
: This is a library that integrates Marshmallow with Flask, making it easy to validate data schemas in your application.marshmallow-sqlalchemy
: This library enables Marshmallow to derive schemas directly from the SQLAlchemy models you create, reducing boilerplate and ensuring consistency.flask-migrate
: This library allows flask to handle incremental database migrations allowing for consistent changes across deployment environments.
To install these dependencies in your local environment, you would need to run the following command:
pip install flask flask-sqlalchemy flask-marshmallow marshmallow-sqlalchemy flask-migrate
Here is the file structure you're going to follow:
├── /app │ ├── /models │ │ └── user.py # User model definition │ ├── /schemas │ │ └── user_schema.py # Marshmallow schema for validation │ ├── /routes │ │ └── user_routes.py # User-related API routes │ ├── __init__.py # App factory │ ├── extensions.py # Initialise SQLAlchemy and Marshmallow │ └── config.py # App configuration ├── run.py # Entry point ├── requirements.txt # Python dependencies └── README.md # Project documentation
- Create Users: Add new users with validation for required fields like
-
Challenge
Define the Database Models
Define the
User
Model Using SQLAlchemyIn this step, you'll:
- Configure the database in the Flask app.
- Define the User model using SQLAlchemy.
- Ensure that the database tables are created properly.
Configure the Database in Flask
SQLAlchemy is an Object Relational Mapper (ORM) that allows you to interact with databases using Python objects instead of raw SQL.
First, modify the
app/extensions.py
file to set up SQLAlchemy so it can be used across the app. In the next task, you are going to make two extensions available to your application. These will allow interaction with the database and the ability to manage migrations. #### ✅ Why Do This?- This keeps your database setup separate from the main application logic.
- You initialize the database once and import
db
wherever it's needed.
Define the
User
ModelNow, you will define the
User
model using SQLAlchemy. #### ✅ What This Does?- Configures SQLite (
sqlite:///database.db
) - Registers SQLAlchemy (
db.init_app(app)
) so it's linked to Flask - Ensures tables exist using
db.create_all()
Creating an App Factory
In this step, you will implement an app factory pattern in Flask. This is a design pattern that allows you to create and configure a Flask application in a modular and reusable way. Instead of defining the app globally, you encapsulate its creation inside a function (
create_app
). This approach provides several benefits:-
Modularity: The app factory allows you to separate the creation and configuration of the Flask app from the rest of the code. This makes it easier to manage and test the application.
-
Reusability: By using a factory function, you can create multiple instances of the app with different configurations (e.g., for testing, development, or production).
-
Dependency Management: The app factory ensures that extensions like SQLAlchemy and Flask-Migrate are properly initialized with the app instance, avoiding circular imports and ensuring clean separation of concerns. Now, you can migrate your database, which will create the database file and prepare it to persist your data.
If you move away from SQLite, all you need to do is change the
DATABASE_URI
string.To initialize your database, run through these three commands:
python3 -m flask db init python3 -m flask db migrate -m "Initial migration" python3 -m flask db upgrade
As you make changes to the schema over time, you can run the
migrate
command to capture the incremental changes to your filesystem.Create an App Entry Point
You can now use the factory you created to instantiate an instance of your app that you can run. The last task in this step is to create an Application Entry Point. With all of these steps completed, you should be able to run your development server with no errors. There are three approaches to this, and you can decide which you prefer.
-
Use
python3
to runapp.py
:python3 run.py
-
Use
python3
to run the Flask library directly:export FLASK_APP=run.py python3 -m flask run
-
Export the app name and run Flask directly:
export FLASK_APP=run.py flask run
You can try all three of these approaches in the Terminal and ensure the server starts without error. You haven't added any routes yet so you won't be able to view anything in your browser.
-
Challenge
Create Marshmallow Schema
In this step, you will create the Marshmallow schema. This is used to serialize and deserialize between your database model and Python objects.
You'll first register Marshmallow within your application and then use it to create your schema.
-
Challenge
Implement CRUD Endpoints
Now, you are ready to start defining and configuring the routes for your API.
As a RESTful API, you should use a consistent naming convention and HTTP methods to define your functionality.
The resource will generally be plural and follow a pattern like the following:
GET /users
- get all of the user resourcesPOST /users
- create a new user resourceGET /users/<user_id>
- get a particular user defined by their idPUT /users/<user_id>
- update a particular userDELETE /users/<user_id>
- delete a particular user
With these routes defined, you'll have a complete RESTful CRUD API.
Each of the following tasks will work through that CRUD cycle step-by-step.
-
Challenge
Test the API with `curl`
As mentioned earlier, there are a few ways to start your API. You should start it in the first Terminal tab and then move to the second Terminal tab.
python3 run.py
Here are the
curl
commands to test the CRUD API for the/api/users
routes of your API:1. Create a User (POST
/api/users
):curl -X POST http://localhost:5000/api/users -H "Content-Type: application/json" -d '{ "username": "johndoe", "email": "johndoe@example.com", "password": "securepassword", "is_active": true }'
Expected Response:
{ "id": 1, "username": "johndoe", "email": "johndoe@example.com", "is_active": true }
2. Get All Users (GET
/api/users
):curl -X GET http://localhost:5000/api/users
Expected Response:
[ { "id": 1, "username": "johndoe", "email": "johndoe@example.com", "is_active": true } ]
3. Get a Single User by ID (GET
/api/users/{user_id}
):curl -X GET http://localhost:5000/api/users/1
Expected Response:
{ "id": 1, "username": "johndoe", "email": "johndoe@example.com", "is_active": true }
4. Update a User (PUT
/api/users/{user_id}
):curl -X PUT http://localhost:5000/api/users/1 -H "Content-Type: application/json" -d '{ "email": "john.doe@newdomain.com", "is_active": false }'
Expected Response:
{ "id": 1, "username": "johndoe", "email": "john.doe@newdomain.com", "is_active": false }
- Delete a User (DELETE
/api/users/{user_id}
):
curl -X DELETE http://localhost:5000/api/users/1
Expected Response:
{ "message": "User deleted successfully" }
Handling Errors
User Not Found (GET)
curl -X GET http://localhost:5000/api/users/999
Expected Response:
{ "error": "User not found" }
Invalid User Creation (POST - Missing Fields)
curl -X POST http://localhost:5000/api/users -H "Content-Type: application/json" -d '{ "username": "janedoe" }'
Expected Response:
{ "error": "Missing required fields" }
These
curl
tests cover all CRUD operations and common error scenarios for your Flask API. # Congratulations!You have now created a RESTful API that allows you to carry out CRUD operations on a given resource.
These skills are transferable across different models or route sets you might build for a given operation.
Good luck in your ongoing API building journey!
- Delete a User (DELETE
What's a lab?
Hands-on Labs are real environments created by industry experts to help you learn. These environments help you gain knowledge and experience, practice without compromising your system, test without risk, destroy without fear, and let you learn from your mistakes. Hands-on Labs: practice your skills before delivering in the real world.
Provided environment for hands-on practice
We will provide the credentials and environment necessary for you to practice right within your browser.
Guided walkthrough
Follow along with the author’s guided walkthrough and build something new in your provided environment!
Did you know?
On average, you retain 75% more of your learning if you get time for practice.