Building Data-Driven Web Apps with Flask and SQLAlchemy Transcripts
Chapter: Database migrations with Alembic
Lecture: More database changes
Login or
purchase this course
to watch this video and the rest of the course contents.
0:00
Let's make one more change so we
0:01
can see the changes chaining together
0:04
as you will appear as we are going.
0:06
So let's add a new table.
0:08
Let's suppose we want to do some auditing
0:10
like, this user logged in or whatever.
0:12
So we're going to go copy and paste one of these model files.
0:17
It's usually the easiest, so we'll just say audit.
0:20
And what we'll want to do is just tell it, your name is Audit
0:26
your table name is Auditing, or something like that
0:29
and id and date is probably good
0:31
and then description, for now that's good enough.
0:34
You know, we probably want the user, the IP address
0:37
the action, things like this but, for now
0:40
just for this example, this is going to be more than enough.
0:44
So we want to have Alembic
0:48
detect this table's added and create it.
0:50
Now you need to be really careful.
0:52
If you run this app now, run the web app
0:55
it's going to actually
0:56
SQLAlchemy will see this table doesn't exist and create it.
0:59
But if you want to make sure that
1:00
Alembic is managing it, don't run the app
1:02
or it's already going to exist and it'll think
1:04
there's no changes, everything is totally in sync.
1:07
And this gets even a little trickier
1:09
in debug mode for Flask
1:10
because Flask will notice this file had changed
1:14
and it will restart the process.
1:15
And the restarting the process will generate that table.
1:18
So be super, super careful about the web app running.
1:21
Basically, have it off if this is something
1:23
that you want to record into Alembic, right?
1:26
Maybe there's relationships between
1:28
the auditing table and the user's table
1:30
and you want to make sure that also gets set up right
1:32
like, foreign keys and whatnot.
1:34
So just turn off the web app, or the auto reload
1:37
may actually create it
1:38
which Alembic will not then detect it.
1:41
All right so let's go over here.
1:42
You can ask the Alembic
1:44
what is your current version?
1:45
It'll say it's this one which is
1:48
actually the head, the latest.
1:50
Now let's go and then ask it to autogenerate
1:55
adding the auditing table.
1:58
Now this is not going to work, I don't think.
2:00
Maybe, maybe not, let's see.
2:02
So we run it, it's generated the file, no doubt.
2:05
But let's see what's in it.
2:07
We go in here, notice it says pass.
2:10
Well, why did it say pass?
2:12
Let's double check over here that our table does not exist.
2:17
Nope, no table. So, is Alembic broken? SQLAlchemy broken?
2:22
No. What's going on?
2:24
Remember our convention here, in this __all_models
2:26
this is how we're telling SQLAlchemy
2:29
here, we're telling it all the models
2:32
that we're going to be using exist in here.
2:34
So we're just going to go and have to add it.
2:37
Don't forget, when you add a new one of these
2:40
always do something like that.
2:42
Okay so this actually did nothing, let's delete it.
2:44
And we'll just generate it again.
2:47
All right, so current is still this, generate the vision.
2:51
Now it's generated it, let's see what we got.
2:55
There we go, now we got something meaningful.
2:57
So it says that revision is the one it created
3:00
and its down revision
3:02
or the one that needs to be run before it
3:05
is a 55, etc., etc.
3:07
What it's going to do is create a table
3:09
it's going to create a bunch of columns in there
3:10
it's going to create a primary key, and an index.
3:13
And to get rid of it, it drops the index
3:16
and drops the table, okay?
3:17
So it's super simple.
3:19
Now though, if we go over here to our terminal
3:22
and we ask Alembic current, it's still the same version
3:25
but that's no longer the head.
3:27
So we want to get the new one.
3:30
We can easily do that again by just going, upgrade to head.
3:36
Run that, we ask what current is.
3:38
It's the new one, now it's head.
3:40
And of course, over here in the database
3:42
if we refresh, we now have our auditing table
3:45
exactly like you would expect.
3:47
How cool is that?
3:48
So Alembic let's us just keep evolving our database;
3:52
however, our SQLAlchemy classes evolve
3:54
we're just going to make sure the database
3:56
does that same thing, which is pretty cool.
3:58
And again, I want to make sure this is in version control
4:00
so let's right away just do an Add
4:03
so we don't forget to commit it.
4:04
We definitely don't want to lose one of those.
4:06
All right, well, now we can just keep going
4:09
with this process, over and over.
4:10
Remember, adding classes, which add the
4:14
add models, which add the tables
4:15
don't forget to add them to all models
4:17
in our convention or find another convention
4:20
and, you know, just keep saving the changes.
4:22
Now, there's one other little utility
4:24
I want to make sure you have access to.
4:26
We're not going to use it, but it could turn out to be helpful.
4:29
We'll talk a tiny bit about it in the concept videos.
4:32
So over here I'm going to drop a file called Alembic Helpers
4:34
and it just for now has one item, but you can have more.
4:38
So basically it gives you a function
4:40
that let's you answer the question
4:42
does a particular table have a particular column?
4:46
And you can see it's using the reflection from the engine
4:50
to go look at it, and things like that.
4:52
Now go look at the tables, and the idea is that
4:55
you know, maybe over here one of these revisions
4:57
you would like to ask
4:59
let's pick the other one where we have a column
5:01
you'd like to ask, I only really want to do this operation
5:04
if the column doesn't exist.
5:06
Maybe you want to just ask first, like
5:08
hey, does this column exist?
5:09
Then I'm going to add it.
5:10
Because what happens if a column does exist
5:13
and you try to run this, it's going to crash.
5:15
It's going to go, ah, I can't create the column
5:18
it already exists, et cetera, et cetera.
5:20
So, you know, some little utilities like this
5:23
can go a long way to make your migrations
5:25
a little more durable and fault tolerant.