Creating the Database (db.create_all)
When you have models, you need to create tables.
For quick demos, you can use db.create_all().
Example
Section titled “Example”from flask import Flask
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///app.db"
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False
db = SQLAlchemy(app)
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(80), unique=True, nullable=False)
with app.app_context():
db.create_all()Why app.app_context()?
Section titled “Why app.app_context()?”Database operations often need the Flask application context.
Important warning
Section titled “Important warning”db.create_all():
- creates missing tables
- does not handle schema changes safely over time
That’s why real apps use migrations (Flask-Migrate).
Use create_all() for:
- learning
- small prototypes
Use migrations for:
- anything you deploy
create_all() creates what is missing, and nothing else
Section titled “create_all() creates what is missing, and nothing else”with app.app_context():
db.create_all()Measured behaviour:
tables now: ['user']
columns: id INTEGER not-null pk, name VARCHAR(20) not-null, age INTEGER not-nullno error, no changeIt is safe to call on every start. It issues CREATE TABLE IF NOT EXISTS for each model
it knows about, so existing tables are left alone.
That last part is also its limitation:
flowchart TD
C["db.create_all()"] --> Q{"does the table exist?"}
Q -->|"no"| N["CREATE TABLE"]
Q -->|"yes"| S["LEAVE IT ALONE
even if the model has changed"]
S --> D["schema drift:
the model and the table disagree,
silently"]
The silent failure that follows
Section titled “The silent failure that follows”Measured: a column was added to the model, create_all() was run again, and the table
was unchanged.
added a column to the model, ran create_all() -> columns still ['id','title','body','views']
no ALTER TABLE, no error, no warningThe application then fails at query time with something like no such column: note.author, far from the change that caused it.
For a development reset, dropping is explicit and obviously destructive:
with app.app_context():
db.drop_all() # deletes every table and everything in them
db.create_all()See it move
Section titled “See it move”Check yourself
Section titled “Check yourself”-
You add a column to a model and run db.create_all() again. What happens to the existing table?
Measured: the columns were unchanged. The mismatch surfaces much later as a query error such as no such column. create_all is not a migration tool.
pch.quizShowAnswer
C — nothing at all: create_all skips tables that already exist, with no error or warning — Measured: the columns were unchanged. The mismatch surfaces much later as a query error such as no such column. create_all is not a migration tool.
-
Is it safe to call db.create_all() every time the app starts?
It issues CREATE TABLE IF NOT EXISTS for each known model. It is harmless to repeat — and equally powerless to update anything.
pch.quizShowAnswer
B — yes: it only creates tables that do not exist, and running it twice measured no error and no change — It issues CREATE TABLE IF NOT EXISTS for each known model. It is harmless to repeat — and equally powerless to update anything.
-
What should you use once a schema needs to change after its first deployment?
flask db migrate diffs models against the database and writes a migration file you can review and roll back. drop_all would destroy production data.
pch.quizShowAnswer
B — Flask-Migrate, which wraps Alembic to generate reviewable ALTER TABLE steps — flask db migrate diffs models against the database and writes a migration file you can review and roll back. drop_all would destroy production data.
pch.coffeeTagline
pch.coffeeCtapch.feedbackHeading
pch.feedbackSubheading