CRUD Applications (5 Part Series)
1 Building a CRUD Application with Node.js, Express, and MongoDB
2 Building a CRUD Application with Node.js, Express, and MySQL
3 Building a CRUD Application with NestJS and MongoDB
4 Building a CRUD Application with Flask and SQLAlchemy
5 Building a CRUD Application with Flask and MongoDB
In this blog, we’ll walk through building a simple CRUD (Create, Read, Update, Delete) API using Flask and SQLAlchemy. This guide will cover setting up the project, configuring the database, defining models, creating routes, and running the application.
Prerequisites
Before getting started, ensure you have the following installed:
- Python 3.x
- Flask
- Flask-SQLAlchemy
- Flask-Migrate
Project Setup
1. Clone the Repository
git clone https://github.com/manthanank/crud-flask-sqlalchemy.git<span>cd </span>crud-flaskgit clone https://github.com/manthanank/crud-flask-sqlalchemy.git <span>cd </span>crud-flaskgit clone https://github.com/manthanank/crud-flask-sqlalchemy.git cd crud-flask
Enter fullscreen mode Exit fullscreen mode
2. Create a Virtual Environment
python <span>-m</span> venv venv<span>source </span>venv/bin/activate <span># On Windows: `venv\Scripts\activate`</span>python <span>-m</span> venv venv <span>source </span>venv/bin/activate <span># On Windows: `venv\Scripts\activate`</span>python -m venv venv source venv/bin/activate # On Windows: `venv\Scripts\activate`
Enter fullscreen mode Exit fullscreen mode
3. Install Dependencies
pip <span>install</span> <span>-r</span> requirements.txtpip <span>install</span> <span>-r</span> requirements.txtpip install -r requirements.txt
Enter fullscreen mode Exit fullscreen mode
Database Configuration
We are using Flask-SQLAlchemy for ORM and Flask-Migrate for database migrations. The database configuration is stored in app/config.py
:
<span>import</span> <span>os</span><span>from</span> <span>dotenv</span> <span>import</span> <span>load_dotenv</span><span>load_dotenv</span><span>()</span><span>class</span> <span>Config</span><span>:</span><span>SQLALCHEMY_DATABASE_URI</span> <span>=</span> <span>os</span><span>.</span><span>getenv</span><span>(</span><span>"</span><span>DATABASE_URL</span><span>"</span><span>,</span> <span>"</span><span>sqlite:///app.db</span><span>"</span><span>)</span><span>SQLALCHEMY_TRACK_MODIFICATIONS</span> <span>=</span> <span>False</span><span>import</span> <span>os</span> <span>from</span> <span>dotenv</span> <span>import</span> <span>load_dotenv</span> <span>load_dotenv</span><span>()</span> <span>class</span> <span>Config</span><span>:</span> <span>SQLALCHEMY_DATABASE_URI</span> <span>=</span> <span>os</span><span>.</span><span>getenv</span><span>(</span><span>"</span><span>DATABASE_URL</span><span>"</span><span>,</span> <span>"</span><span>sqlite:///app.db</span><span>"</span><span>)</span> <span>SQLALCHEMY_TRACK_MODIFICATIONS</span> <span>=</span> <span>False</span>import os from dotenv import load_dotenv load_dotenv() class Config: SQLALCHEMY_DATABASE_URI = os.getenv("DATABASE_URL", "sqlite:///app.db") SQLALCHEMY_TRACK_MODIFICATIONS = False
Enter fullscreen mode Exit fullscreen mode
Initializing the Database
To set up the database, run the following commands:
flask db initflask db migrate <span>-m</span> <span>"Initial migration"</span>flask db upgradeflask db init flask db migrate <span>-m</span> <span>"Initial migration"</span> flask db upgradeflask db init flask db migrate -m "Initial migration" flask db upgrade
Enter fullscreen mode Exit fullscreen mode
On Windows, before running these commands, set the environment variable:
<span>set </span><span>FLASK_APP</span><span>=</span>run.py<span>set </span><span>FLASK_APP</span><span>=</span>run.pyset FLASK_APP=run.py
Enter fullscreen mode Exit fullscreen mode
Defining the Model
We define a simple Item
model in app/models.py
:
<span>from</span> <span>app</span> <span>import</span> <span>db</span><span>class</span> <span>Item</span><span>(</span><span>db</span><span>.</span><span>Model</span><span>):</span><span>id</span> <span>=</span> <span>db</span><span>.</span><span>Column</span><span>(</span><span>db</span><span>.</span><span>Integer</span><span>,</span> <span>primary_key</span><span>=</span><span>True</span><span>)</span><span>name</span> <span>=</span> <span>db</span><span>.</span><span>Column</span><span>(</span><span>db</span><span>.</span><span>String</span><span>(</span><span>100</span><span>),</span> <span>nullable</span><span>=</span><span>False</span><span>)</span><span>description</span> <span>=</span> <span>db</span><span>.</span><span>Column</span><span>(</span><span>db</span><span>.</span><span>String</span><span>(</span><span>200</span><span>))</span><span>def</span> <span>to_dict</span><span>(</span><span>self</span><span>):</span><span>return</span> <span>{</span><span>"</span><span>id</span><span>"</span><span>:</span> <span>self</span><span>.</span><span>id</span><span>,</span> <span>"</span><span>name</span><span>"</span><span>:</span> <span>self</span><span>.</span><span>name</span><span>,</span> <span>"</span><span>description</span><span>"</span><span>:</span> <span>self</span><span>.</span><span>description</span><span>}</span><span>from</span> <span>app</span> <span>import</span> <span>db</span> <span>class</span> <span>Item</span><span>(</span><span>db</span><span>.</span><span>Model</span><span>):</span> <span>id</span> <span>=</span> <span>db</span><span>.</span><span>Column</span><span>(</span><span>db</span><span>.</span><span>Integer</span><span>,</span> <span>primary_key</span><span>=</span><span>True</span><span>)</span> <span>name</span> <span>=</span> <span>db</span><span>.</span><span>Column</span><span>(</span><span>db</span><span>.</span><span>String</span><span>(</span><span>100</span><span>),</span> <span>nullable</span><span>=</span><span>False</span><span>)</span> <span>description</span> <span>=</span> <span>db</span><span>.</span><span>Column</span><span>(</span><span>db</span><span>.</span><span>String</span><span>(</span><span>200</span><span>))</span> <span>def</span> <span>to_dict</span><span>(</span><span>self</span><span>):</span> <span>return</span> <span>{</span><span>"</span><span>id</span><span>"</span><span>:</span> <span>self</span><span>.</span><span>id</span><span>,</span> <span>"</span><span>name</span><span>"</span><span>:</span> <span>self</span><span>.</span><span>name</span><span>,</span> <span>"</span><span>description</span><span>"</span><span>:</span> <span>self</span><span>.</span><span>description</span><span>}</span>from app import db class Item(db.Model): id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(100), nullable=False) description = db.Column(db.String(200)) def to_dict(self): return {"id": self.id, "name": self.name, "description": self.description}
Enter fullscreen mode Exit fullscreen mode
Creating the API Routes
In app/routes.py
, we define the API endpoints for CRUD operations using Flask’s Blueprints:
1. Create an Item
<span>@api_bp.route</span><span>(</span><span>"</span><span>/items</span><span>"</span><span>,</span> <span>methods</span><span>=</span><span>[</span><span>"</span><span>POST</span><span>"</span><span>])</span><span>def</span> <span>create_item</span><span>():</span><span>data</span> <span>=</span> <span>request</span><span>.</span><span>json</span><span>new_item</span> <span>=</span> <span>Item</span><span>(</span><span>name</span><span>=</span><span>data</span><span>[</span><span>"</span><span>name</span><span>"</span><span>],</span> <span>description</span><span>=</span><span>data</span><span>.</span><span>get</span><span>(</span><span>"</span><span>description</span><span>"</span><span>))</span><span>db</span><span>.</span><span>session</span><span>.</span><span>add</span><span>(</span><span>new_item</span><span>)</span><span>db</span><span>.</span><span>session</span><span>.</span><span>commit</span><span>()</span><span>return</span> <span>jsonify</span><span>(</span><span>new_item</span><span>.</span><span>to_dict</span><span>()),</span> <span>201</span><span>@api_bp.route</span><span>(</span><span>"</span><span>/items</span><span>"</span><span>,</span> <span>methods</span><span>=</span><span>[</span><span>"</span><span>POST</span><span>"</span><span>])</span> <span>def</span> <span>create_item</span><span>():</span> <span>data</span> <span>=</span> <span>request</span><span>.</span><span>json</span> <span>new_item</span> <span>=</span> <span>Item</span><span>(</span><span>name</span><span>=</span><span>data</span><span>[</span><span>"</span><span>name</span><span>"</span><span>],</span> <span>description</span><span>=</span><span>data</span><span>.</span><span>get</span><span>(</span><span>"</span><span>description</span><span>"</span><span>))</span> <span>db</span><span>.</span><span>session</span><span>.</span><span>add</span><span>(</span><span>new_item</span><span>)</span> <span>db</span><span>.</span><span>session</span><span>.</span><span>commit</span><span>()</span> <span>return</span> <span>jsonify</span><span>(</span><span>new_item</span><span>.</span><span>to_dict</span><span>()),</span> <span>201</span>@api_bp.route("/items", methods=["POST"]) def create_item(): data = request.json new_item = Item(name=data["name"], description=data.get("description")) db.session.add(new_item) db.session.commit() return jsonify(new_item.to_dict()), 201
Enter fullscreen mode Exit fullscreen mode
2. Retrieve All Items
<span>@api_bp.route</span><span>(</span><span>"</span><span>/items</span><span>"</span><span>,</span> <span>methods</span><span>=</span><span>[</span><span>"</span><span>GET</span><span>"</span><span>])</span><span>def</span> <span>get_items</span><span>():</span><span>items</span> <span>=</span> <span>Item</span><span>.</span><span>query</span><span>.</span><span>all</span><span>()</span><span>return</span> <span>jsonify</span><span>([</span><span>item</span><span>.</span><span>to_dict</span><span>()</span> <span>for</span> <span>item</span> <span>in</span> <span>items</span><span>])</span><span>@api_bp.route</span><span>(</span><span>"</span><span>/items</span><span>"</span><span>,</span> <span>methods</span><span>=</span><span>[</span><span>"</span><span>GET</span><span>"</span><span>])</span> <span>def</span> <span>get_items</span><span>():</span> <span>items</span> <span>=</span> <span>Item</span><span>.</span><span>query</span><span>.</span><span>all</span><span>()</span> <span>return</span> <span>jsonify</span><span>([</span><span>item</span><span>.</span><span>to_dict</span><span>()</span> <span>for</span> <span>item</span> <span>in</span> <span>items</span><span>])</span>@api_bp.route("/items", methods=["GET"]) def get_items(): items = Item.query.all() return jsonify([item.to_dict() for item in items])
Enter fullscreen mode Exit fullscreen mode
3. Retrieve a Single Item
<span>@api_bp.route</span><span>(</span><span>"</span><span>/items/<int:item_id></span><span>"</span><span>,</span> <span>methods</span><span>=</span><span>[</span><span>"</span><span>GET</span><span>"</span><span>])</span><span>def</span> <span>get_item</span><span>(</span><span>item_id</span><span>):</span><span>item</span> <span>=</span> <span>Item</span><span>.</span><span>query</span><span>.</span><span>get_or_404</span><span>(</span><span>item_id</span><span>)</span><span>return</span> <span>jsonify</span><span>(</span><span>item</span><span>.</span><span>to_dict</span><span>())</span><span>@api_bp.route</span><span>(</span><span>"</span><span>/items/<int:item_id></span><span>"</span><span>,</span> <span>methods</span><span>=</span><span>[</span><span>"</span><span>GET</span><span>"</span><span>])</span> <span>def</span> <span>get_item</span><span>(</span><span>item_id</span><span>):</span> <span>item</span> <span>=</span> <span>Item</span><span>.</span><span>query</span><span>.</span><span>get_or_404</span><span>(</span><span>item_id</span><span>)</span> <span>return</span> <span>jsonify</span><span>(</span><span>item</span><span>.</span><span>to_dict</span><span>())</span>@api_bp.route("/items/<int:item_id>", methods=["GET"]) def get_item(item_id): item = Item.query.get_or_404(item_id) return jsonify(item.to_dict())
Enter fullscreen mode Exit fullscreen mode
4. Update an Item
<span>@api_bp.route</span><span>(</span><span>"</span><span>/items/<int:item_id></span><span>"</span><span>,</span> <span>methods</span><span>=</span><span>[</span><span>"</span><span>PUT</span><span>"</span><span>])</span><span>def</span> <span>update_item</span><span>(</span><span>item_id</span><span>):</span><span>item</span> <span>=</span> <span>Item</span><span>.</span><span>query</span><span>.</span><span>get_or_404</span><span>(</span><span>item_id</span><span>)</span><span>data</span> <span>=</span> <span>request</span><span>.</span><span>json</span><span>item</span><span>.</span><span>name</span> <span>=</span> <span>data</span><span>.</span><span>get</span><span>(</span><span>"</span><span>name</span><span>"</span><span>,</span> <span>item</span><span>.</span><span>name</span><span>)</span><span>item</span><span>.</span><span>description</span> <span>=</span> <span>data</span><span>.</span><span>get</span><span>(</span><span>"</span><span>description</span><span>"</span><span>,</span> <span>item</span><span>.</span><span>description</span><span>)</span><span>db</span><span>.</span><span>session</span><span>.</span><span>commit</span><span>()</span><span>return</span> <span>jsonify</span><span>(</span><span>item</span><span>.</span><span>to_dict</span><span>())</span><span>@api_bp.route</span><span>(</span><span>"</span><span>/items/<int:item_id></span><span>"</span><span>,</span> <span>methods</span><span>=</span><span>[</span><span>"</span><span>PUT</span><span>"</span><span>])</span> <span>def</span> <span>update_item</span><span>(</span><span>item_id</span><span>):</span> <span>item</span> <span>=</span> <span>Item</span><span>.</span><span>query</span><span>.</span><span>get_or_404</span><span>(</span><span>item_id</span><span>)</span> <span>data</span> <span>=</span> <span>request</span><span>.</span><span>json</span> <span>item</span><span>.</span><span>name</span> <span>=</span> <span>data</span><span>.</span><span>get</span><span>(</span><span>"</span><span>name</span><span>"</span><span>,</span> <span>item</span><span>.</span><span>name</span><span>)</span> <span>item</span><span>.</span><span>description</span> <span>=</span> <span>data</span><span>.</span><span>get</span><span>(</span><span>"</span><span>description</span><span>"</span><span>,</span> <span>item</span><span>.</span><span>description</span><span>)</span> <span>db</span><span>.</span><span>session</span><span>.</span><span>commit</span><span>()</span> <span>return</span> <span>jsonify</span><span>(</span><span>item</span><span>.</span><span>to_dict</span><span>())</span>@api_bp.route("/items/<int:item_id>", methods=["PUT"]) def update_item(item_id): item = Item.query.get_or_404(item_id) data = request.json item.name = data.get("name", item.name) item.description = data.get("description", item.description) db.session.commit() return jsonify(item.to_dict())
Enter fullscreen mode Exit fullscreen mode
5. Delete an Item
<span>@api_bp.route</span><span>(</span><span>"</span><span>/items/<int:item_id></span><span>"</span><span>,</span> <span>methods</span><span>=</span><span>[</span><span>"</span><span>DELETE</span><span>"</span><span>])</span><span>def</span> <span>delete_item</span><span>(</span><span>item_id</span><span>):</span><span>item</span> <span>=</span> <span>Item</span><span>.</span><span>query</span><span>.</span><span>get_or_404</span><span>(</span><span>item_id</span><span>)</span><span>db</span><span>.</span><span>session</span><span>.</span><span>delete</span><span>(</span><span>item</span><span>)</span><span>db</span><span>.</span><span>session</span><span>.</span><span>commit</span><span>()</span><span>return</span> <span>jsonify</span><span>({</span><span>"</span><span>message</span><span>"</span><span>:</span> <span>"</span><span>Item deleted successfully</span><span>"</span><span>})</span><span>@api_bp.route</span><span>(</span><span>"</span><span>/items/<int:item_id></span><span>"</span><span>,</span> <span>methods</span><span>=</span><span>[</span><span>"</span><span>DELETE</span><span>"</span><span>])</span> <span>def</span> <span>delete_item</span><span>(</span><span>item_id</span><span>):</span> <span>item</span> <span>=</span> <span>Item</span><span>.</span><span>query</span><span>.</span><span>get_or_404</span><span>(</span><span>item_id</span><span>)</span> <span>db</span><span>.</span><span>session</span><span>.</span><span>delete</span><span>(</span><span>item</span><span>)</span> <span>db</span><span>.</span><span>session</span><span>.</span><span>commit</span><span>()</span> <span>return</span> <span>jsonify</span><span>({</span><span>"</span><span>message</span><span>"</span><span>:</span> <span>"</span><span>Item deleted successfully</span><span>"</span><span>})</span>@api_bp.route("/items/<int:item_id>", methods=["DELETE"]) def delete_item(item_id): item = Item.query.get_or_404(item_id) db.session.delete(item) db.session.commit() return jsonify({"message": "Item deleted successfully"})
Enter fullscreen mode Exit fullscreen mode
Setup Environment Variables
.env
DATABASE_URL=sqlite:///app.dbDATABASE_URL=sqlite:///app.dbDATABASE_URL=sqlite:///app.db
Enter fullscreen mode Exit fullscreen mode
Running the Application
Run the Flask application with:
python run.pypython run.pypython run.py
Enter fullscreen mode Exit fullscreen mode
The API will be accessible at http://127.0.0.1:5000/api/items
.
API Endpoints
Method | Endpoint | Description |
---|---|---|
POST | /api/items |
Create a new item |
GET | /api/items |
Get all items |
GET | /api/items/<id> |
Get a single item |
PUT | /api/items/<id> |
Update an item |
DELETE | /api/items/<id> |
Delete an item |
Testing the API
You can test the API using Postman or cURL.
- Create an Item:
curl <span>-X</span> POST http://127.0.0.1:5000/api/items <span>-H</span> <span>"Content-Type: application/json"</span> <span>-d</span> <span>'{"name": "Laptop", "description": "Gaming laptop"}'</span>curl <span>-X</span> POST http://127.0.0.1:5000/api/items <span>-H</span> <span>"Content-Type: application/json"</span> <span>-d</span> <span>'{"name": "Laptop", "description": "Gaming laptop"}'</span>curl -X POST http://127.0.0.1:5000/api/items -H "Content-Type: application/json" -d '{"name": "Laptop", "description": "Gaming laptop"}'
Enter fullscreen mode Exit fullscreen mode
- Get All Items:
curl <span>-X</span> GET http://127.0.0.1:5000/api/itemscurl <span>-X</span> GET http://127.0.0.1:5000/api/itemscurl -X GET http://127.0.0.1:5000/api/items
Enter fullscreen mode Exit fullscreen mode
- Get a Specific Item:
curl <span>-X</span> GET http://127.0.0.1:5000/api/items/1curl <span>-X</span> GET http://127.0.0.1:5000/api/items/1curl -X GET http://127.0.0.1:5000/api/items/1
Enter fullscreen mode Exit fullscreen mode
- Update an Item:
curl <span>-X</span> PUT http://127.0.0.1:5000/api/items/1 <span>-H</span> <span>"Content-Type: application/json"</span> <span>-d</span> <span>'{"name": "Updated Laptop", "description": "High-performance gaming laptop"}'</span>curl <span>-X</span> PUT http://127.0.0.1:5000/api/items/1 <span>-H</span> <span>"Content-Type: application/json"</span> <span>-d</span> <span>'{"name": "Updated Laptop", "description": "High-performance gaming laptop"}'</span>curl -X PUT http://127.0.0.1:5000/api/items/1 -H "Content-Type: application/json" -d '{"name": "Updated Laptop", "description": "High-performance gaming laptop"}'
Enter fullscreen mode Exit fullscreen mode
- Delete an Item:
curl <span>-X</span> DELETE http://127.0.0.1:5000/api/items/1curl <span>-X</span> DELETE http://127.0.0.1:5000/api/items/1curl -X DELETE http://127.0.0.1:5000/api/items/1
Enter fullscreen mode Exit fullscreen mode
Conclusion
In this guide, we built a Flask CRUD API using SQLAlchemy for database operations and Flask-Migrate for migrations. This setup provides a solid foundation for building RESTful services in Flask.
Congratulations! You’ve built a Flask CRUD API with SQLAlchemy.
Happy coding!
Exploring the Code
Visit the GitHub repository to explore the code in detail.
CRUD Applications (5 Part Series)
1 Building a CRUD Application with Node.js, Express, and MongoDB
2 Building a CRUD Application with Node.js, Express, and MySQL
3 Building a CRUD Application with NestJS and MongoDB
4 Building a CRUD Application with Flask and SQLAlchemy
5 Building a CRUD Application with Flask and MongoDB
暂无评论内容