|
|
|
# FastAPI + SQLModel + Alembic
|
|
|
|
|
|
|
|
Following the https://testdriven.io/blog/fastapi-sqlmodel/ blog post
|
|
|
|
|
|
|
|
## Docker Containers
|
|
|
|
|
|
|
|
Bring it up
|
|
|
|
```
|
|
|
|
docker-compose up -d --build
|
|
|
|
```
|
|
|
|
|
|
|
|
*NOTE* changes in your are reflected in the web container since we are mounting
|
|
|
|
it as a local volume, and we are serving it using uvicorn from the target mount.
|
|
|
|
```
|
|
|
|
volumes:
|
|
|
|
- ./project:/usr/src/app
|
|
|
|
```
|
|
|
|
|
|
|
|
Shut it down
|
|
|
|
```
|
|
|
|
docker-compose down -v
|
|
|
|
```
|
|
|
|
The -v removes names volumes declared in the `volumes` section of the compose
|
|
|
|
file and anonymous volumes attached to containers
|
|
|
|
|
|
|
|
### Logs
|
|
|
|
|
|
|
|
```
|
|
|
|
docker-compose logs web
|
|
|
|
```
|
|
|
|
You'll see what is logged to stdout. Should include your new models on startup.
|
|
|
|
|
|
|
|
or
|
|
|
|
|
|
|
|
```
|
|
|
|
docker-compose logs db
|
|
|
|
```
|
|
|
|
|
|
|
|
### PSQL for working in your DB
|
|
|
|
```
|
|
|
|
docker-compose exec db psql --username=postgres --dbname=foo
|
|
|
|
```
|
|
|
|
|
|
|
|
```
|
|
|
|
foo=# \dt
|
|
|
|
List of relations
|
|
|
|
Schema | Name | Type | Owner
|
|
|
|
--------+------+-------+----------
|
|
|
|
public | song | table | postgres
|
|
|
|
```
|
|
|
|
|
|
|
|
### Running Alembic code
|
|
|
|
|
|
|
|
See: https://alembic.sqlalchemy.org/en/latest/cookbook.html#using-asyncio-with-alembic
|
|
|
|
|
|
|
|
#### Init Alembic
|
|
|
|
|
|
|
|
Creates the initial needfuls from alembic. Run it in our container because we don't
|
|
|
|
have a local env. We initialize it with the async template also
|
|
|
|
```
|
|
|
|
docker-compose exec web alembic init -t async migrations
|
|
|
|
```
|
|
|
|
|
|
|
|
Note we had to modify a lot of the generated code from the above command
|
|
|
|
for this to work with SQLModel and the models it produces.
|
|
|
|
|
|
|
|
#### First Migration
|
|
|
|
|
|
|
|
```
|
|
|
|
docker-compose exec web alembic revision --autogenerate -m "init"
|
|
|
|
```
|
|
|
|
|
|
|
|
As second migration example
|
|
|
|
|
|
|
|
*IMPORTANT*
|
|
|
|
The `--autogenerate` works off of inspecting the running DB schema against your code
|
|
|
|
to see if anything is going to change. Your DB needs to be running to generate these
|
|
|
|
autogenerated changes. Or you could just write your own file by hand. Which could
|
|
|
|
happen in more complicated applications.
|
|
|
|
|
|
|
|
```
|
|
|
|
docker-compose exec web alembic revision --autogenerate -m "add year to Song Model"
|
|
|
|
```
|
|
|
|
|
|
|
|
#### Applying the Migrations
|
|
|
|
|
|
|
|
```
|
|
|
|
docker-compose exec web alembic upgrade head
|
|
|
|
```
|
|
|
|
|
|
|
|
If we wanted to get ambitious we could use an entrypoint script
|
|
|
|
that will run alembic migrations for us on container start. You did this in
|
|
|
|
your Wagtail tutorial stuff.
|
|
|
|
|
|
|
|
## Interactions with API
|
|
|
|
|
|
|
|
### Add a song
|
|
|
|
|
|
|
|
```
|
|
|
|
curl -d '{"name":"Midnight Fit", "artist":"Mogwai"}' \
|
|
|
|
-H "Content-Type: application/json" -X POST http://localhost:8004/songs
|
|
|
|
```
|
|
|
|
Response:
|
|
|
|
```
|
|
|
|
{"id":1,"artist":"Mogwai","name":"Midnight Fit"}%
|
|
|
|
```
|
|
|
|
|
|
|
|
With the new optional song year
|
|
|
|
```
|
|
|
|
curl -d '{"name":"Midnight Fit", "artist":"Mogwai", "year": 2021}' \
|
|
|
|
-H "Content-Type: application/json" -X POST http://localhost:8004/songs
|
|
|
|
```
|
|
|
|
|
|
|
|
Response:
|
|
|
|
```
|
|
|
|
{"id":2,"name":"Snakes","artist":"Miyavi","year":2021}
|
|
|
|
```
|
|
|
|
|
|
|
|
## Sources Root in Pycharm
|
|
|
|
|
|
|
|
I marked "project" directory as the "Sources Root". PyCharm uses the source roots as the starting point for
|
|
|
|
resolving imports.
|