An Object - Relational Mapping (ORM) is a programming technique that allows developers to interact with a database using object - oriented concepts. Instead of writing raw SQL queries, an ORM maps database tables to Python classes, rows to class instances, and columns to class attributes. This makes the code more readable, maintainable, and less error - prone.
SQLAlchemy provides two main styles of working: Core and ORM. The Core is a lower - level SQL abstraction layer, while the ORM builds on top of the Core to provide a higher - level, object - oriented interface. SQLAlchemy supports multiple database backends such as MySQL, PostgreSQL, SQLite, etc.
Flask - SQLAlchemy is an extension for Flask that simplifies the use of SQLAlchemy in Flask applications. It provides a simple way to configure the database connection and manage database sessions.
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
# Configure the database URI
app.config['SQLALCHEMY_DATABASE_URI'] ='sqlite:///test.db'
# Initialize the SQLAlchemy object
db = SQLAlchemy(app)
@app.route('/')
def index():
return 'Hello, World!'
if __name__ == '__main__':
app.run(debug=True)
In this code, we first import the necessary modules. Then we create a Flask application and configure the database URI. The SQLALCHEMY_DATABASE_URI
specifies the location and type of the database. Finally, we initialize the SQLAlchemy
object with the Flask application.
A database model in SQLAlchemy is a Python class that represents a database table. Each attribute of the class corresponds to a column in the table.
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] ='sqlite:///test.db'
db = SQLAlchemy(app)
# Define a model
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(80), nullable=False)
email = db.Column(db.String(120), unique=True, nullable=False)
def __repr__(self):
return '<User %r>' % self.name
# Create the database tables
with app.app_context():
db.create_all()
@app.route('/')
def index():
return 'Database tables created!'
if __name__ == '__main__':
app.run(debug=True)
Here, we define a User
model with three columns: id
, name
, and email
. The id
is the primary key, and the email
column has a unique constraint. The __repr__
method is used to provide a string representation of the object. We then create the database tables using db.create_all()
within the application context.
Once the model is defined, we can add new records to the database and query existing records.
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] ='sqlite:///test.db'
db = SQLAlchemy(app)
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(80), nullable=False)
email = db.Column(db.String(120), unique=True, nullable=False)
def __repr__(self):
return '<User %r>' % self.name
with app.app_context():
db.create_all()
# Add a new user
new_user = User(name='John Doe', email='[email protected]')
db.session.add(new_user)
db.session.commit()
# Query all users
users = User.query.all()
for user in users:
print(user)
@app.route('/')
def index():
return 'Data added and queried!'
if __name__ == '__main__':
app.run(debug=True)
In this code, we first create a new User
object and add it to the database session using db.session.add()
. Then we commit the changes to the database using db.session.commit()
. To query all users, we use User.query.all()
.
We can also update and delete existing records in the database.
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] ='sqlite:///test.db'
db = SQLAlchemy(app)
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(80), nullable=False)
email = db.Column(db.String(120), unique=True, nullable=False)
def __repr__(self):
return '<User %r>' % self.name
with app.app_context():
db.create_all()
# Add a new user
new_user = User(name='John Doe', email='[email protected]')
db.session.add(new_user)
db.session.commit()
# Update a user
user = User.query.filter_by(name='John Doe').first()
user.email = '[email protected]'
db.session.commit()
# Delete a user
user_to_delete = User.query.filter_by(name='John Doe').first()
db.session.delete(user_to_delete)
db.session.commit()
@app.route('/')
def index():
return 'Data updated and deleted!'
if __name__ == '__main__':
app.run(debug=True)
To update a user, we first query the user by name, then modify the attribute, and finally commit the changes. To delete a user, we query the user and use db.session.delete()
followed by db.session.commit()
.
If the SQLALCHEMY_DATABASE_URI
is misconfigured, Flask - SQLAlchemy will not be able to connect to the database. For example, if the database file path is incorrect for SQLite or the database server credentials are wrong for MySQL/PostgreSQL.
Failing to properly manage database sessions can lead to issues such as data not being committed or memory leaks. Always remember to call db.session.commit()
after making changes to the database and db.session.rollback()
in case of errors.
If the database schema changes (e.g., adding a new column to a table) and the model is not updated accordingly, SQLAlchemy may raise errors when querying or inserting data.
Storing the database URI in environment variables is a good practice. This makes it easier to deploy the application in different environments (development, testing, production) without hard - coding the database credentials.
import os
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = os.environ.get('DATABASE_URI','sqlite:///test.db')
db = SQLAlchemy(app)
As the application evolves, the database schema may change. Using a database migration tool like Flask - Migrate allows you to manage these changes in a controlled way. Flask - Migrate uses Alembic under the hood to generate and apply database migrations.
Keep the database models, routes, and other application logic in separate files. This makes the code more modular and easier to maintain. For example, you can create a models.py
file to store all the database models.
Using SQLAlchemy with Flask provides a powerful and flexible way to interact with databases in Flask applications. By understanding the core concepts, typical usage scenarios, common pitfalls, and best practices, developers can build robust and scalable web applications. With the ability to abstract away the complexities of raw SQL queries, SQLAlchemy allows developers to focus on the application logic rather than the database operations.