Building a CRUD Application with Flask and SQLAlchemy

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-flask
git clone https://github.com/manthanank/crud-flask-sqlalchemy.git
<span>cd </span>crud-flask
git 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.txt
pip <span>install</span> <span>-r</span> requirements.txt
pip 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 init
flask db migrate <span>-m</span> <span>"Initial migration"</span>
flask db upgrade
flask db init
flask db migrate <span>-m</span> <span>"Initial migration"</span>
flask db upgrade
flask 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.py
set 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.db
DATABASE_URL=sqlite:///app.db
DATABASE_URL=sqlite:///app.db

Enter fullscreen mode Exit fullscreen mode

Running the Application

Run the Flask application with:

python run.py
python run.py
python 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/items
  curl <span>-X</span> GET http://127.0.0.1:5000/api/items
curl -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/1
  curl <span>-X</span> GET http://127.0.0.1:5000/api/items/1
curl -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/1
  curl <span>-X</span> DELETE http://127.0.0.1:5000/api/items/1
curl -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

原文链接:Building a CRUD Application with Flask and SQLAlchemy

© 版权声明
THE END
喜欢就支持一下吧
点赞8 分享
We’d better struggle for the future rather than regret for the past.
如果后悔过去,不如奋斗将来
评论 抢沙发

请登录后发表评论

    暂无评论内容