Skip to content

Commit

Permalink
finish v1
Browse files Browse the repository at this point in the history
  • Loading branch information
professor-ben committed Sep 6, 2022
1 parent 188e70d commit b0db8d0
Show file tree
Hide file tree
Showing 9 changed files with 191 additions and 230 deletions.
188 changes: 179 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ Flask-Migrate in your virtual environment. Enter the following in
`flask_app.py`:

```py
# app/flask_app.py

#!/usr/bin/env python3

from flask import Flask
Expand Down Expand Up @@ -95,6 +97,8 @@ contains all of the same fields as attributes. This behaves similarly to
Let's create some models!

```py
# app/models.py

from flask_sqlalchemy import SQLAlchemy

db = SQLAlchemy()
Expand All @@ -111,7 +115,7 @@ class Owner(db.Model):
return f'<Pet Owner {self.name}>'

class Pet(db.Model):
__tablename__ = 'users'
__tablename__ = 'pets'

id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String)
Expand All @@ -136,15 +140,181 @@ from our models using Flask-Migrate.

### Flask-Migrate

Like Flask-SQLAlchemy with vanilla SQLAlchemy, Flask-Migrate is a wrapper for
Alembic with minimal changes to allow it to integrate better with Flask
applications. This can become a bit confusing, especially from the command line.
Don't worry though- we'll discuss those nuances in detail here!

Modify `flask_app.py` to mirror the following:

```py
# app/flask_app.py

#!/usr/bin/env python3

from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate

from models import db

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///app.db'

db = SQLAlchemy(app)

migrate = Migrate(app, db)

db.init_app(app)

if __name__ == '__main__':
app.run()

```

We have imported the `Migrate` class here to set up our migrations using our
Flask application instance and our `SQLAlchemy` instance. We also initialized
our application for use within our database configuration with
`db.init_app(app)`.

> **NOTE:** `db.init_app(app)` is an easy step to forget! (So don't!)
We're ready to get started with our migrations. The commands for Flask-Migrate
are identical to those in Alembic, with the exception of using `flask db` in
place of `alembic` in commands. Run the following from the `app/` directory in
the command line:

```console
$ export FLASK_APP=flask_app.py
$ flask db init
# => /python-p4-flask-sqlalchemy/.venv/lib/python3.10/site-packages/flask_sqlalchemy/__init__.py:872: FSADeprecationWarning: SQLALCHEMY_TRACK_MODIFICATIONS adds significant overhead and will be disabled by default in the future. Set it to True or False to suppress this warning.
# => warnings.warn(FSADeprecationWarning(
# => /python-p4-flask-sqlalchemy/.venv/lib/python3.10/site-packages/flask_sqlalchemy/__init__.py:872: FSADeprecationWarning: SQLALCHEMY_TRACK_MODIFICATIONS adds significant overhead and will be disabled by default in the future. Set it to True or False to suppress this warning.
# => warnings.warn(FSADeprecationWarning(
# => Creating directory /python-p4-flask-sqlalchemy/app/migrations ... done
# => Creating directory /python-p4-flask-sqlalchemy/app/migrations/versions ... done
# => Generating /python-p4-flask-sqlalchemy/app/migrations/script.py.mako ... done
# => Generating /python-p4-flask-sqlalchemy/app/migrations/env.py ... done
# => Generating /python-p4-flask-sqlalchemy/app/migrations/README ... done
# => Generating /python-p4-flask-sqlalchemy/app/migrations/alembic.ini ... done
# => Please edit configuration/connection/logging settings in '/python-p4-flask-sqlalchemy/app/migrations/alembic.ini' before proceeding.
```

Let's heed that warning and set `SQLALCHEMY_TRACK_MODIFICATIONS` to `False`.

```py
# app/flask_app.py

...
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///app.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
...

```

We're getting a warning to change `app/migrations/alembic.ini` before we
continue, but our `app/flask_app.py` configuration already manages all of our
unique environment variables. We can jump straight into migrating:

```console
$ flask db revision --autogenerate -m'Create tables owners, pets'
# => INFO [alembic.runtime.migration] Context impl SQLiteImpl.
# => INFO [alembic.runtime.migration] Will assume non-transactional DDL.
# => Generating /python-p4-flask-sqlalchemy/app/migrations/versions/a48f1fc37e07_create_tables_owners_pets.py ... done
```

...and pushing those migrations to our database:

```console
$ flask db upgrade head
# => INFO [alembic.runtime.migration] Context impl SQLiteImpl.
# => INFO [alembic.runtime.migration] Will assume non-transactional DDL.
# => INFO [alembic.runtime.migration] Running upgrade -> 1c84830b3fc2, Create tables owners, pets
```

We've created a database with Flask-SQLAlchemy and Flask-Migrate! Open
`app/db/app.db` and you should see the fruits of your labor:

![Screenshot of SQLite database with three tables: alembic_version, owners, and
pets](
https://curriculum-content.s3.amazonaws.com/python/flask-sqlalchemy-owners-pets-db.png)

***

## Resources
## Conclusion

Flask extensions give us many opportunities to add functionality to our
applications while writing minimal code for configurations. We saw how to
create a database with Flask-SQLAlchemy and Flask-Migrate, and some among us
may have even noticed that we wrote slightly _less_ code than we did when using
SQLAlchemy by itself!

In the next lesson, we will look into working with data in Flask applications
using Flask-SQLAlchemy.

***

## Solution Code

```py
# app/flask_app.py

- [API - Pallets Projects](https://flask.palletsprojects.com/en/2.2.x/api/)
- [HTTP request methods - Mozilla][moz_http]
- [HTTP response status codes - Mozilla][moz_http_status]
- [Response Objects - Pallets Projects][response]
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate

from models import db

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///db/app.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False

migrate = Migrate(app, db)

db.init_app(app)

if __name__ == '__main__':
app.run()

```

```py
# app/models.py

from flask_sqlalchemy import SQLAlchemy

db = SQLAlchemy()

class Owner(db.Model):
__tablename__ = 'owners'

id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String, unique=True)

pets = db.relationship('Pet', backref='owner')

def __repr__(self):
return f'<Pet Owner {self.name}>'

class Pet(db.Model):
__tablename__ = 'pets'

id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String)
species = db.Column(db.String)

owner_id = db.Column(db.Integer, db.ForeignKey('owners.id'))

def __repr__(self):
return f'<Pet {self.name}, {self.species}>'

```

***

## Resources

[moz_http]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods
[moz_http_status]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status
[response]: https://flask.palletsprojects.com/en/2.2.x/api/#response-objects
- [Quickstart - Flask-SQLAlchemy](https://flask-sqlalchemy.palletsprojects.com/en/2.x/quickstart/#)
- [Flask-Migrate](https://flask-migrate.readthedocs.io/en/latest/)
- [Flask Extensions, Plug-ins, and Related Libraries - Full Stack Python](https://www.fullstackpython.com/flask-extensions-plug-ins-related-libraries.html)
Binary file removed app/db/app.db
Binary file not shown.
5 changes: 2 additions & 3 deletions app/flask_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,8 @@
from models import db

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///app.db'

db = SQLAlchemy(app)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///db/app.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False

migrate = Migrate(app, db)

Expand Down
1 change: 0 additions & 1 deletion app/migrations/README

This file was deleted.

50 changes: 0 additions & 50 deletions app/migrations/alembic.ini

This file was deleted.

91 changes: 0 additions & 91 deletions app/migrations/env.py

This file was deleted.

24 changes: 0 additions & 24 deletions app/migrations/script.py.mako

This file was deleted.

Loading

0 comments on commit b0db8d0

Please sign in to comment.