In this chapter, you will learn to define data models with Flask-SQLAlchemy, create SQLite database tables, and insert test data.
* * *
## Why use ORM?
Directly writing SQL statements to operate databases is cumbersome and error-prone.
ORM (Object-Relational Mapping) allows you to define table structures using Python classes and manipulate data using Python methods.
Flask-SQLAlchemy is Flask's integration version of SQLAlchemy, encapsulating common operations and making configuration simpler.
* * *
## Installation and Configuration
(venv) $ pip install flask-sqlalchemy
## Example
# File path: app.py
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
app = Flask( __name__ )
# SQLite database file path (located in the project root directory)
app.config['SQLALCHEMY_DATABASE_URI']='sqlite:///blog.db'
# Disable modification tracking (saves memory, will be disabled by default in future versions)
app.config['SQLALCHEMY_TRACK_MODIFICATIONS']=False
# Create db instance, bind to app
db = SQLAlchemy(app)
> The three slashes in `sqlite:///blog.db` indicate a relative path. SQLite database is just a file, without needing to install any database software, making it very suitable for development and testing.
* * *
## Defining Models: Post and Category
## Example
# File path: models.py
from datetime import datetime
from app import db
class Category(db.Model):
"""Article category"""
__tablename__ ='categories'
id= db.Column(db.Integer, primary_key=True, autoincrement=True)
name = db.Column(db.String(50), unique=True, nullable=False)
slug = db.Column(db.String(50), unique=True, nullable=False)
# backref: can use .posts on Category object to reverse retrieve all articles under it
posts = db.relationship('Post', backref='category', lazy='dynamic')
def __repr__ (self):
return f'
'
class Post(db.Model):
"""Blog article"""
__tablename__ ='posts'
id= db.Column(db.Integer, primary_key=True, autoincrement=True)
title = db.Column(db.String(200), nullable=False)
slug = db.Column(db.String(200), unique=True, nullable=False)
summary = db.Column(db.Text, default='')
content = db.Column(db.Text, nullable=False)
# Foreign key: db.ForeignKey('table name.field name')
category_id = db.Column(db.Integer, db.ForeignKey('categories.id'), nullable=False)
created_at = db.Column(db.DateTime, default=datetime.utcnow)
updated_at = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
def __repr__ (self):
return f''
### Common Field Types
| Field Type | Database Type | Common Parameters |
| --- | --- | --- |
| db.Integer | INTEGER | primary_key, autoincrement |
| db.String(N) | VARCHAR(N) | unique, nullable, default |
| db.Text | TEXT | default |
| db.DateTime | DATETIME | default, onupdate |
| db.Boolean | BOOLEAN | default |
| db.ForeignKey('table.field') | FOREIGN KEY | β |
* * *
## Creating Database Tables
Unlike Django's migrate, Flask requires manually initializing database tables.
(venv) $ flask shell # Enter Flask interactive Shell
## Example
# Input in flask shell
from app import db
db.create_all()# Create all database tables corresponding to models
exit()
After execution, the `blog.db` file will be generated in the project root directory.
> `db.create_all()` only creates tables if they don't exist. If you modify the model structure (such as adding new fields), it won't automatically update the table. In production environments, you should use Flask-Migrate (Chapter 5) to manage structural changes.
* * *
## Inserting Test Data with flask shell
## Example
# Input in flask shell
from app import db
from models import Category, Post
# 1. Create categories
py_cat = Category(name='Python', slug='python')
css_cat = Category(name='CSS', slug='css')
flask_cat = Category(name='Flask', slug='flask')
db.session.add_all([py_cat, css_cat, flask_cat])
db.session.commit()
# 2. Create articles
post1 = Post(
title='Flask Complete Beginner's Guide',
slug='flask-beginner-guide',
summary='Start learning Flask from scratch, covering core concepts such as routing, templates, ORM, etc.',
content='Why learn Flask?
Flask is Python The most flexible Web micro-framework...
',
category=flask_cat
)
post2 =