Welcome back, everyone, to this lecture series, we're a first time to talk about updating models
and then we'll talk about updating entries in those models.
So there may come a time when need to create a new column or attribute for a model.
And you can easily update existing models by simply adding a new model class attribute and then migrating
those changes.
You should note, however, that when you're adding new fields, that is attributes to the model class,
the existing entries will need to have some sort of default value inserted, even if it's just a null
value.
In fact, when we attempt to run these migrations without taking care of these sort of default value
issues that are going to occur for the existing entries, Chengdu will actually specifically request
us to make a decision, which is actually quite nice that we don't encounter errors further down the
line.
So jingles actually helping you by making sure you make the correct sort of adjustments for existing
entries.
Now, you're typically given two options when you run those migrations and you haven't chosen a default
value.
You either choose a default value on the spot, right when you create that migration file, or you can
cancel the migration file in general and then create a default value within the model.
It's technically kind of the same thing.
One just delays it.
And has you fixed the model?
The other one just does it on the spot.
I would say it's usually more robust to have the default live in the actual model instead of deciding
they're at the command line.
But keep in mind, each case is different, but again, it's usually better to have some sort of default
value actually defined within your models, not pie.
OK, so let's explore these ideas further in our code, and we're also going to touch on the idea of
using validators within fields which add hardcoded constraints that are going to reject non valid entries.
Let's head back to our code editor.
OK, so here we are back inside of models, not PI.
And let's imagine for our patients, we'd also like to keep track of some sort of biological statistic,
maybe their heart rate.
So every time they come into the office, we go ahead and take their heart rate.
That way, we can take a record in our database and understand what their heart rate was last time or
what their current heart rate is.
Maybe you would want this to be a list, but right now we're just going pretend it's a single integer
that gets updated and rewritten every time there's a patient.
So, for example, I can say heart rate.
Is a new attribute.
For this patient, and it's also going to be an integer, so we're going to say model integer field.
OK, now, if I just leave it like this, there's a couple of things.
One is I would need to decide some sort of default value for this integer, for the existing patients,
because all the existing patients in our database technically don't have some value for heart rate,
we haven't actually assigned that yet.
So let's see what happens if I try to actually make migrations.
So I'm going to save this change in models that PI.
So I had control s there.
And then what I'm going to do is say Python managed our pie, make migrations office hit enter and you'll
see this warning.
Basically, it says it's impossible to add a non knowable field heart rate to patient without specifying
a default.
So this already fantastic that Django is helping us out so much in such clear language, it's saying
this is because the data needs something to populate existing rows.
As I mentioned, the existing patients now actually have any heart rate value.
So then it offers you two options.
If you pass the number one, then it allows you to provide a one off default now, which is going to
be set on all existing rows.
Pay no value for this column or two.
You can quit and manually define a default value in models that pay.
As I mentioned, I would usually recommend you to choose number two here in order to actually hard code
the default value.
Again, every situation is different, so maybe there are going to be instances where you just want
to provide a one off default that overwrites the existing rows with wood having no value.
But in general, I would say go ahead and choose Option two.
This will essentially quit this migration, and you won't have to worry about that migration file.
And now what we can do is inside of integer field, I can set a default and you could do this for any
field, and the default value could be something like the average heart rate of maybe 60 beats per minute.
Now again, it totally depends on the situation of what's a reasonable default or not.
And you can even have a no value as your default, and there's many different ways to doing that.
But you could also say something like null is equal to true, which essentially allows us to just be
blank or a no value.
But I'm going to say my default value is going to be 60 beats per minute.
Now the other thing I want to take into consideration is later on when we are accepting patients and
I'm typing in their first name, last name and age, maybe I want to actually perform some sort of validation
on those numbers.
For example, I don't want someone working at the front desk to accidentally say someone has a heart
rate of or a resting heart rate of something like zero beats per minute because that's impossible.
I mean, that person is basically that.
I also want to make sure that the age range is something reasonable.
This is where validators come into play.
So we end up saying the imports for validation can come for like this, we're going to say from jingo
dark core dot validators.
Imports.
And then there's a bunch of built in validators, and you can check these out if you just Google, search
Django validators.
There is a documentation page on validators.
You can technically write your own custom validators.
But a lot of times the built in ones are more than enough for us, like a URL validator or the fact
that there's min and max value, as well as min and maxlength validators.
So you can see here there's a min value validator, as well as a max length validator.
So let's see how we actually use these going to come back here.
The first thing is we actually import those classes, so I'm going to import Max.
Value validator, and I'm also going to import Min value validator, so from jingo without core that
validators, you import the relevant validators.
Let's step number one.
And if you're wondering what validators are available to you, you simply check the documentation here.
OK, so now that I have the validators ready, then I can go to whatever fields need some sort of validation
check.
And I can say the following like h.
I can say validators is equal to.
And then I just pass any list of the instances of those validators.
So, for example, max value validator, if I take a look at that in the documentation, I can see that
it's a class call and it essentially just takes in a limit value.
You can also rewrite the message that is reported back, but typically the validation error code is
enough and informative enough for you.
Not need to do that.
Instead, just really focus on what's the limiting value.
So what's the max value?
Someone could have for agent?
What's a minimum value someone can have for age?
We come back here and we can say the following.
So my first validator is going to be a min value for essentially an instance of min value validator.
And here I'm going to say the minimum age is zero.
So that's my limit.
Then I add one for max value validator, and this one may be a little trickier because it's like, what's
the maximum age I'm allowing a patient to have?
I'm going to say something like one hundred and twenty.
Maybe that's too young.
Who knows?
In the future we're living to be 130, 150 years old, but for right now, we'll say that's OK.
That way, if someone accidentally types in one hundred and fifty, they're going to get an error and
saying, sorry, that's out of the validation range.
So let's add some validators for the heart rate as well.
So we're going to say validators.
Equals and then we're going to add in some Min Max validators as well.
So I'm going to grab these two validators and let's pass those into our list.
I'm also going to say that the validators that essentially the minimum value, let's say it's I'm the
one heart rate or one beat per minute for their heart rate.
I'm not a doctor, so it'll be kind of up to a specialist to decide what a reasonable minimum and maximum
values here.
And we'll say maybe a maximum value is like three hundred or something.
Obviously, if your heart rate is either three hundred beats per minute or one beats per minute, you
are probably in a serious situation.
But we're going to leave that as kind of just some sort of reality check to make sure we don't get an
entry of like a thousand or something like that.
Essentially, just to make sure we don't get typos later on.
OK, so now we go ahead and save those changes.
And remember, I have a new default value here.
I could technically add defaults for first name, last name and age, but I think heart rate is quite
reasonable to have a default value versus first name.
You kind of don't want a default value there because that assumes that someone is just going to come
in and not give you their first name as a new patient.
So we're gonna expand this again, and let's try running that migrations command again.
So I'm saying Python managed the pie make migrations office.
Remember to save those changes in models, not pie.
So adding in those validators here after we import them and pass them into that list, also just do
a quick double check to make sure parentheses and brackets are OK.
Note that the validators is a list of instances of validation classes.
Then what I'm going to do is go ahead and run, make migrations.
And no.
Now we have a new migrations file.
So as I mentioned underneath the migrations folder, you get these kind of list of historical migrations.
So let's check it out.
What happens when we do another migration?
We can see we have dependencies.
So what are these dependencies?
It's saying it's dependent on the initial file, which is nice because that actually allows you to then
in the future, roll back changes in case you want to undo this migration.
And then you can see here it's going to add fields like it's adding a new heart rate field and it's
also altering field.
It's altering the existing field, and it's just altering it with some validators.
So this is actually quite readable.
Again, as I mentioned, we don't typically edit these migration files, but it is nice to understand
what's going on inside of them.
So once we're OK with that again, we typically don't check that migration file was actually going to
run this migration.
So we're going to say Python managed that pie migrate to enter, and then it applied those migrations.
OK.
So that's the very basics of updating your model.
Again, you just add in attributes and you may need to think about what defaults are reasonable given
what you're working with.
Ian, we also talked about adding in validators.
Coming up next, we're going to talk about updating existing entries in our database table.
I'll see you there.