Welcome back, everyone, to part two of creating the website and the models that will later on be analyzing
through the admin panel.
So so far, we've completed some very basic views that essentially just report back the rendering of
the HTML.
We completed the basic URL routing, created a general navigation bar and then we have a list of empty
templates list, add and delete.
Now we're going to do is we're going to create a very simple car model.
It's just going to have a brand and a year associated with it.
Then we're going to add some functionality to the views to actually connect to the model using what
we already know about model and objects and being able to request or delete or get a list of them.
And then finally, this is the last part.
And it's also kind of the hardest we need to create HTML forms to send information back to the views.
That way, we can actually add in a new object directly from the HTML as a client user on the browser
side.
A really important note before we continue is the methods shown here are going to be using, quote unquote
raw HTML forms that we learned about in the HTML section to accept user information regarding a model
in the database.
And they're really not ideal.
Later on, we're going to learn about the Django form system, which is much, much better.
So don't worry too much about having to apply.
We're going to show here to your jingo projects later on because in the very next section of the course,
we're going to learn about jingle forms, which makes this entire process of trying to create a forum
to accept information from the user.
Super easy.
However, since we technically don't know about that yet, I'm going to stick to just basic HTML forms.
It's not too bad, but the jingle forms are really much cleaner and much nicer, much better.
OK, let's get started.
I'm going to jump right back in where we left off last time.
All right.
So here we are, back where we left off last time.
We have these views, which are very simple.
They just connect to the HTML.
We will be editing these views and the corresponding HTML.
Later on in this lecture.
But first, let's actually create the model that we're going to be working with.
So we're going to come to models that pie and I'm going to create an instance of the car model.
So I'm going to say class car and let's inherit from models thought model.
This is going to be a very simple model.
Recall that models by default are going to be able to have a primary key associated with them.
That's what we're going to use as our unique identifier, so we won't need to actually add that in ourselves
instead.
We'll let the user define a car by specifying a brand and a year.
So I will say brand is equal to models that and that will be a character field, let's say, with a
max length of 30 characters.
Next is going to be a year attribute that's going to be an integer field.
And lastly, we want to have some sort of string representation of a car that way when we display on
the HTML.
I can actually see something.
So I'll say the f underscore, underscore S.T.A.R. underscore, underscore, underscore, underscore
the RICO percent self.
And then I'm just going to return using f string literal formatting.
Car is.
And let's go ahead and say self-taught brand space self-taught year.
OK.
Save those changes.
So what I have so far is a really simple car class.
It's going to have an index based off a primary key when it's created starting at one and then it's
going to have a brand in a year that do need to be defined when we actually create a new instance of
a car.
We don't need to worry about the primary key, as we already know from our discussion of models.
That's automatically created for you.
So let's go ahead and make migrations for models, and then we'll just migrate everything.
So I'm going to say Python.
Manage that pie.
Make migrations.
And then I'm going to do it for the Cars app.
Hit enter.
It should have created a new migration file for you, initialed that you can confirm that by Checking
Under Migrations folder, we have our initial Dot Pi migration notice again.
It has Automatic ID primary key created for us and that it has the brand and the year.
So once that's done, let's actually run the migrations.
So we're going to say.
Python.
Manage that pie, migrate, and when you enter here, you should actually see a bunch of migrations.
You're going to see all the migrations for administration, authentication authorization and then cars
as well as well as sessions.
So you should see a bunch of those there.
As I mentioned before, sometimes you just run, migrate right off the bat, then create your models,
then make migrations, then migrate.
I just did it all in one step there, so it should be see a bunch of migrations.
Just make sure it's confirmed that you were able to apply your initial cars migration.
After you do that, you should also see somewhere around here DB that SQL like three.
That's where we're going to be storing the data.
So we have our models ready to go.
Now it's just a matter of editing the views in order to list all the cars, add new cars and delete
cars.
Let's start off with the simplest one, which should be listing.
So we'll come back to views and then we're going to do is be able to create a request for all the cars,
send it back as a context object to list thought HTML.
So from views that pie.
What I'm going to do here is, say, the following I will say from the import models.
And then I'm going to say the list of all the cars is equal to models, the car, the objects, the
all.
So remember, we actually finished the model's lecture by showing you a little example like this.
Remember all cars that's going to be all the car objects we currently have in our database.
But to send it back to list the HTML, I do need this to be a dictionary.
So I will say that my context dictionary is just going to be a key.
All cars that matches up with all cars, the variable.
And then I send back context.
Equal to context.
OK.
Go ahead and save that change now list.
HTML does need to be updated to actually expect this context and list out all the cars there.
So how do we do that?
We're going to come back to list that HTML.
So let me open that up and explore the Riko list.
HTML.
So far, it just says lists HTML.
Well, we want to do is let's create a div here, and I'm going to give this div a container class because
we remember we are using bootstrap.
I do extend it from basic HTML heading one.
Inside this container just for organization purposes.
And then after that, I'm just going to build out an unordered list, so I'll say unordered list, and
then we use the for loop, really for Django template tag.
We're going to say for car in all cars.
Then we'll create a list item, which itself.
Is going to be that car object.
And remember, for every four, we have to end the four.
So I call end for.
And this should actually be one word.
There we go.
So we've actually seen this example before, again, all we're saying is here's this h html create an
unordered list and then create as many list items as necessary for every car in all cars.
What is all cars?
After you save that change, you can come back here and check it out.
All cars is simply the key value pairing here, which is going to be models that car objects to all.
So that's the list view.
Technically speaking, I could just run the website right now, but I wouldn't actually see any results
because we haven't added anything manually into our database.
So let's now move on to a slightly more complex task, which is how do we actually add in a new car
given the HTML?
So this one's slightly more complicated.
This one actually probably makes more sense to now start off from the HTML side of things.
That way, I can set up my form and understand what I'm actually sending back.
So we're going to open up, add HTML and keep in mind, we're later on going to learn how to use jingle
forms to do this and a much cleaner fashion.
But I'm just going to set up a div here again.
Let's have it be class container, so it looks a little nicer.
I'll put an ad HTML inside this container.
And then what we need to do is set up a form, so right below this each one, what I'll do is start
creating a form.
And then this form essentially has a couple of main inputs, we need it to accept a brand except a year
and then have a submit button.
So for that, I am going to say input.
And let's also make a label.
For this input, and in fact, let's put this entire label input grouping inside a div in case you want
to separate out for styling purposes later.
So what I did here?
Is I have now.
A div and inside of that div is a label and put this first one is going to be for brand.
I'm going to copy and paste it again.
And the second one will be for the year of the car.
Remember, this is a form and then the user on the website will be able to add in a new car with a brand
and a year.
So if you want, you can add in another heading to here that says, add a new car, add a new car to
the database.
OK, and then remember, at the very bottom, we should have some sort of submit button salsa input
type of to submit.
And then what we have here is our label.
So let's start off with the brand.
So we're going to say brand of car is the actual text the label shows.
Second, one is going to be here and then I'm going to have both of them be text type.
And we're just going to say this is for I'm going to call this brand and let's give this an I.D..
Equal to brand.
So they're connected as well as the name.
Equal to brands, so they're connected.
Other the same thing here, except it's all going to be here.
So this label is for a year.
We'll give this the ID year, so it's connected.
And let's give it the name year.
Recall, the name is what's actually going to be passed in connected to the value.
The name is essentially the key value pair, and it's the key side.
The value being whatever input the user actually provides for us if you want, you can actually begin
to style this with some class calls with with bootstrap.
Last thing, however, that we do need here is going to be a method call.
So we need to say method is equal to in this case, we're posting information to the database.
So I will say post.
Keep in mind, we'll show you a much better way of doing this entire form later on Django Farms.
But we have a pretty simple form here.
Just takes in a brand a year and then a submit button.
Let's very quickly check to make sure this is looking all right when we actually run our website.
So at the very bottom here, what I'm going to do, scroll down and say Python.
Managed a pie run server.
Keep in mind, I don't actually expect this form to work in any sense, so we're going to say go to
that web page and this is going to be a forward slash cars forward slash ad.
And it should look something like this a little ugly because there's no CSI styling.
But it says at each meal, at a new carts, at the bay debate to the database brand a year and then
hit submit.
Nothing's going to happen.
In fact, we should probably see an error if we try to fill this out with some sort of no submit.
And it says, see, it's RF verification fail.
See SRF or cross site request.
Forgery is actually a mechanism that's implemented for you with jingo in order to make sure that there's
not some sort of hacking attempt being done through this form.
Now we will cover that in a lot more detail later on, but basically the solution here is in the template.
There needs to be this c SRF underscore token template tag, so I'm just going to copy this.
I won't explain what this really does for you right now.
Just have to take my word for it that that tokenism is saying.
And here's the instruction how to do that?
Add in that template tag to the actual form in order to have the post form operate.
So copy that and then inside the form, what are you going to do?
Is simply paste in this jingo tag that's going to let Django know it's OK.
It's not a hacking attempt.
You can go ahead and check their CSR token.
More details on that to come.
When we actually talk about Django forms next, what I want to do is add a little bit of styling, so
this looks OK.
Something I can do is use the form group class.
So inside each of these devs, you can say class is equal to form group.
And that will style it just a little nicer here.
So when you see that change and then come back to the actual page and refresh it, it should look a
little nicer.
Also, what I'm going to add in is another piece of class here, which is called the form control that
goes into the inputs.
So I'm essentially just copying and pasting this from the documentation.
So for the imports, I'm using class form control on the inputs.
And if you want, you can also add a button class here.
So I can say class is equal to, let's say, BTN.
That and let's come back to.
This is going to go back to add a female, and now it looks a lot nicer.
OK, and we see the submit button.
It's actually not colored.
So let's make it BTN Primary.
To say BTN primary, save that change and refresh.
And there you have it.
Ah, submit button as you want, can a little break element first and spacing?
Don't worry too much about styling right now.
It's really not important for us.
OK, so we have an HTML.
This is a form now that can accept a brand and a year, but there is absolutely no connection to anything
to happen on that from the viewpoint of things.
So we're ready to pass that information.
Now we need to let the view know what to do.
Right now, it's just going to keep rendering at HTML.
So if we try to submit something again here, like, let's say, Toyota and the years 1990 for that
Toyota hit submit, it essentially nothing happens.
It's just going to say, Hey, I had a post request, but I'm not doing anything with it.
So what do we need to do on The View's side of things?
Well, for one, we have to take care of two situations.
The first situation is the user comes to the page and wants to add a car.
The second situation is the users already on the page and then hit submit for their request to post
information, which means under AD actually need an if statement.
I need to say if and then what's going to happen is I can check if there's actually a post request.
So we can say if request that post and then I can do something here just to show you what's actually
happening here.
What I'm going to do is print.
Request the post.
So go ahead and say print requests that post here.
Save that change and then come back to add HTML.
And then you may need to refresh this, a go to list and go to add that's a good way of refreshing it
instead of if sometimes if you click refresh here, it asks you to resubmit the form.
So now I'm going to say Toyota.
Toyota announcing in 1990 hit submit again, nothing really happens here, but now take a look at what's
happening in the terminal.
We actually did print a query dictionary note that it has this middle token where this middleware token,
that's the CSR f, essentially making sure it's a legit entry.
And now we have brand and the year.
This is essentially a dictionary like object that actually grab information from.
So if there is a post request, I can then grab Brand Toyota and Year 1990, which is exactly what we're
going to do here.
So I have an if statement that says if.
Requests that post.
Then my brand is equal to request that post, remember, this is essentially a dictionary.
So I grabbed the brand from that key and then say the year is equal to and then it's going to be requests
that post.
Yea.
Keep in mind, years, technically a string here, so I will cast it to be an integer.
All right.
And then finally, now that I have the brand and I can create a new object by saying models that car
the objects and I can use create, I can also create an instance of a car object and then save it.
But remember, this is how we do it all at once.
So we say brand is equal to brand and we say year is equal to year.
Knowing full well that the ID with the primary key can be automatically created for us, so this is
what happens if there's a request post.
I grabbed the brand, I grabbed the year and then I am going to go ahead and create that object.
Keep in mind, we are assuming a lot here.
We can assume that the year will in fact be able to be converted to an integer.
So we're not going to have a bunch of things like tri statements.
Maybe we'll do a little bit that end the leap, but we're just going to assume that the user smart enough
to put this in correctly.
And then once they've actually created the car, let's go ahead and redirect the user to the list page
and we're going to use a redirect reverse for that.
So I come back up here, I'm going to import render and I'm also going to import redirect.
And then I also need to import reverse, so we're going to say from jingo that Earle's import reverse,
if you're a little fuzzy on redirect and reversed, you may want to review back in the URL routing discussion
when we talked about things like HTP response.
So go ahead and check out a redirect and reverse in case you're a little fuzzy on that, but it's actually
quite simple to use.
Once we've created that new model car, I'm going to say is return a redirect and then find me a reverse
for the view and the URL name I want to go to is on their cars colon list.
This essentially just says that.
If user submitted new car.
Then go to list HTML now you may be wondering how to actually know its cars.
Colin list, that's actually the find here in URLs.
Top high cars comes from the app named cars and list comes from the name list here.
That's how that works.
This is exactly the same as the URL names we were able to insert in the actual template for the nafaa.
If you've got a basic HTML, that's this right here.
Car's colon list exact same logic on reverse reverse basically just says, Hey, look up the application
called cars and then find me that name for the URL route called list.
Then once you've looked up that HTML, go ahead and redirect them to that template.
So that's if the request is post.
However, if they haven't actually posted anything yet, we still want to render the actual ad html.
So here I say else, make sure it's aligned with that if statement, I say else.
Return cars at each table.
Now go ahead and save that change.
And go ahead and refresh your page.
So best way to refresh this again is come here, go to list list is blank right now, let's try adding
a new car.
So here we'll say Toyota is the brand.
And also the years 1990 I hit submit.
And now it redirects me to list a still car, is Toyota 1990.
Perfect.
Let's try it one more time.
And when I say Brand is going to be Honda.
And let's make this on the year 2000 submit.
And I see cars Toyota 1990 car is Honda 2000.
Remember, each of these has primary keys, primary key of one, primary key of two and so on.
Now I could add another car that is a repeat, so they don't have to be unique.
I can have another Toyota with another 1990 year.
And that's totally OK.
These still are unique cars because of the primary key.
So when I'm thinking of deleting a car through a form, I want to end up deleting based off the primary
key.
So that form is going to be super simple.
It's basically going to ask, Hey, what's the primary key you want to delete?
So we're going to come back to delete the email and then let's fill this one up.
And again, super simple, here I create a div.
This nerve is going to have a container class just to make things look nice.
It's going to still report back that we're on the delete page just for a curly.
And then let's create a form here, action.
We don't actually redirect anything through the form.
We're just doing that through Django.
This again, will be post.
And then add in your token here so you don't get an error.
So we'll say C s r f token.
Remember, this is a tag comes in watching jingo.
And let's create a div here.
And then add in a label and add in input very similar to what we just did, except this time the idea
would be, Hey, I'm looking for the primary key number you want to delete.
So let's Al-Sadd in a heading to.
And to speak to the car.
And heading once, actually, OK.
So I have this label, I just need to fill this out.
We're going to say it's for pick that label.
And now let's add in the.
I'd.
Is peak.
And let's also add in the name is.
P.K..
And then finally, if you want to make this look a little nicer, you can add some classes here.
I can say this is class.
Form group, and we can say this is class form control.
This is just from get bootstrap dot com.
Finally, we do need to have an input button here, so we're going to say input type is going to be.
Submit.
Save that, if you want, can add in the class, call for the button between B10 primary.
So that change.
All right.
So I got kind of fast for that, but it's just a repeat of what we just did for AD created a form.
Make sure has that CSR token create a div?
This is essentially just accepting a primary key number.
So we do expect this to be just an integer like one, two, three, four, etc..
And the other thing that to do here is I could add in a little warning if there's an issue, but I'm
just going to save it for now and we'll come back to views and fill out the delete.
Let's actually make sure that our form is showing up.
So I'll come back here and instead of list, I will go to delete.
And here it's working.
Enter Piqué to the car.
This is just going to accept the number like one or two, etc..
Now what happens if the enter a number like 100 or 1000 or we don't have a car for that where it's going
to redirect them to go back to the list page and then nothing will actually happen in order to make
sure we don't get a full kind of meltdown about trying to delete something that doesn't exist here.
I will do the following and say if.
Request that post.
Then I'm going to delete the car.
Else, if they're just on that page, I will render cars delete.
So how do we delete a car?
Well, first and you understand what's the primary key of the car wants to delete?
I'll say P.K. as equal to request post.
And then I will try to delete that car.
So let's create a try accept statement here.
If I want to try to delete the car, I simply say models, the car capital car, the objects that get
and here I'll say pick is equal to pick and then I will call.
Delete.
And then I'm going to return a redirect.
Reverse for cars list, just as we did before.
Now let's imagine they pass in one thousand, in which case there is no cars that ID.
What do I do there?
I could just give a little message here in the terminal, it says Prince became not found.
And then do the redirect.
Later on, we'll learn about something called Jingle Messages, which actually lets us inform the user
right then and there.
Hey, I couldn't find the picture.
We don't know about that yet, so we'll just ignore that.
So we'll still return.
To the redirect.
Go ahead and save that change.
So, again, really similar, except now just a form excepting a peak.
It's going to try to delete that and then redirect if it is not able to actually find that pick.
I mean, this tribe locked in at work, it's going to just reverse and go back to the cars list.
If there isn't a request submitted, yeah, then it's going to render the delete form.
So we'll come back here.
And make sure to kind of refresh this so good a list.
Let's try the leading cars to the 1990.
I know that P.K. is one, so I'll come back to the last person, the number one hit submit.
And there you go, it removed it.
I know cars Honda 20.
That should be equal to two because it's the second entry.
Remember those primary keys?
They don't get suddenly updated that way.
Everything gets re shifted or something.
Everybody keeps that same primary key, unique identifier for essentially the rest of our life in this
database.
So let's try.
The leading car is Honda.
I'll hit the list here.
Pick number is to hit submit, and there it is.
So I have one car left.
Let's hit, delete, and let's try a number that doesn't work like 10000 hit submit and nothing happened.
I went back to list, but it should see now somewhere in this terminal.
If I expand this, it should see somewhere.
If I see the full report, they'll say, Here it is.
Peak not found.
All right.
So now I have the ability to add, delete and list items inside my database, all from the user part
of things.
You should again, keep in mind, Jenga forms is going to make this way cleaner and way nicer, but
we have enough here to work with so that it makes sense and now view the administration panel.
I'm going to do a really quick overview of everything we just did because we did introduce some new
concepts.
But if you want, you should be good to go for the next lecture or begin talking about admin.
But let me give you a quick 60 second overview of everything we just did.
So we essentially set up our models that pay to create a car class.
The car automatically has this primary I.D. column and then it accepts a brand and a year and a string
representation of that car using that string representation of the car.
I'm able to then on list 8's HTML, just say car for car and all cars.
All cars is actually the result of a query on my list of you asking for all the cars inside the car
model database.
And then it sends it back as context list HTML.
Then I wanted to add new cars to the database.
So then I had add html.
I created a form has this security token and then it has a question for the brand and a question for
the year and it submits it back.
How does it submit it back?
Well, it's omits it back, essentially as a query dictionary object, which means I check, Hey, if
there was a post request, then if that request post grabbed the brand, grabbed the year and then create
a new car object with that brand and year and then redirect to the list page so they can see that out
of there if there's not a request post.
It means that users just visiting that page for the first time render at HTML.
Similar idea for delete If there is a request, grab the primary key to delete because this could have
an error if they pass in the wrong primary key, I'm going to try it first and then otherwise I can
accept and still do a redirect.
Keep in mind, we could have done a try except here as well in case they pass the a year that was just
like a string or something and wasn't an integer.
You can always be more and more clever with trying to try and accept things that the user may make a
mistake on.
All right.
That's the very basics of what we just did.
Coming up next, we'll talk about the admin panel.
I'll see you there.