-: Hi guys and welcome back.
In this video, we're going to start looking at the code
that we're giving you for this project.
Because we've already built a few of these database
using command line apps, we figured it would be best
to give you some code so that we don't have
to write everything from scratch.
Everything we're going to give you though,
we already know how to write.
We've already covered this in previous sections,
so there's nothing new here.
Everything that's new, we haven't written yet,
we're gonna write that over the next few videos.
So, let's get started.
Here I've opened the poll project in PyCharm,
you can download all of this starter code
with the resources section of this lecture
and we have a few files.
First of all, something new, the requirements.txd
just contains the libraries that you need
in order to run this project.
When you open up the requirements.txd,
you can see the libraries you need,
you can just go ahead and instal them
and these are the versions of those libraries.
Notice the two equal signs in here is just the syntax used
in requirements.txt files to signal
what version of the library we're using.
We've also got a .env file with a new instance URL
and that's just something I've just created in ElephantSQL.
You can create one and put it in there as well
and .env.example with a database you arrive in.
Then, we get to the meat of it.
We've got app.py and database.py.
Let's first talk about database.py.
We've got three tables in this project:
polls, options, and votes.
I'm just gonna close the left-hand side
so that we get a better view of this code.
In the polls table, we have three columns.
The id, which is a serial primary key,
the title, which is text, and the owner,
or the user that created this poll.
Know that this owner is not a foreign key
to some user's table, it's just a string there
for us to identify who created the poll.
It's not unique or anything like that.
The options table has again three columns:
the id, which is another primary key, serial as well,
the option text or what people are going
to be voting for, and the poll id.
This is a foreign key onto the polls table.
So, these two are related through that.
Finally, we've got the votes table, which has
the user name of the person who voted,
as well as the option that they voted for.
We don't need the poll id here because options have
a unique id and they are related to polls,
so we can find out the poll by going through options.
The FOREIGN_KEY here is option_id and it references
the options table id column.
We've got a couple of queries in here to select all
the polls and to select poll with options by using a join.
That just gives us the poll information as well as each
of the options in the table, given a poll id.
And to insert a new option and to insert a new vote.
So we've got a bunch of things missing here,
like to insert polls and stuff like that,
but we're gonna be adding those as we go along.
Then for these queries we've got our functions.
Nothing new here as well, they each take a connection,
create a cursor, and then run the appropriate queries,
like to create the different tables, to select polls
and then there's cursor.fetchall.
Here get_latest_poll is something we're gonna use
to get the latest poll that was added to the database.
This, I've put pass in here,
because we haven't implemented yet.
We're gonna use some new knowledge in order to do that
so this is, at the moment, unimplemented.
Getting poll details, we need a poll id,
and then we're just gonna SELECT_POLL_WITH_OPTIONS,
that just gives us essentially everything about a poll
and then we return cursor.fetchall.
To get a poll and the vote results that includes
the vote percentage associated with it,
we've got pass in there at the moment,
we're gonna be implementing there later on.
To get a random poll vote which would give us
essentially the winner on a poll, we've got pass as well,
we're gonna be implementing that later on.
Creating a poll because it takes in the title
and the owner as well as the options,
we're gonna be implementing this later on as well.
And finally to add a poll vote, that's just
the INSERT_VOTE there, so we've got that running there.
All right, so not much new in database.py,
but again, that was of course the point of this,
not to give you anything too new.
Now we're gonna go over to app.py
and I'll show you what we've got in here,
which is quite a bit, so please bear with me.
The imports, you may get an error here saying
DivisionByZero is not a class inside psycopg2.errors.
What I've done is I've just ignored that
so on here you can essentially click ignore
if you do get that error.
If you're using VS code or anything
like that that's not PyCharm,
you're not gonna get an error, that's fine.
This works, it's just due to how psychopg2 is built
that it gives an error in PyCharm.
Then we've got our constant database prompt
asking the user for the database URI.
The menu prompt to show him the different options
in the menu and the new option prompt when we have
to add new options into a poll,
that just tells the user what to do.
So, to create a poll, we're going to ask the user
for a title and the owner of the poll,
then we're gonna create an empty options list,
and then we're gonna use this walrus operator
that we've looked at before to keep adding new options
to this list as strings until they enter an empty string,
and then we're gonna pass all of that to create poll.
So at the moment, this is not implemented, the create_poll,
so we're gonna look at that later on.
To list the open polls, we're just gonna do
database.get_polls and then we're gonna destruction in here,
the different poll fields, and we're gonna print them out.
Prompting for a vote, we're gonna ask for the poll id
that the user wants to vote on,
we're gonna get its details, we're gonna print
the different options out, and then we're gonna ask them
for which option they want to vote for as well as
what their username is and we're gonna pass
all of that data to add_poll_vote.
Printing the polls options just goes through them
and prints their details out.
We're gonna look into more detail
as to how this works in just a moment.
And then show_poll_votes is gonna essentially ask the user
for the poll that they wanna see votes for,
then it's gonna get the count and percentage
of votes for each option in a poll
using database.get_poll_and_vote_results.
We haven't implemented this yet, but we will do.
And this can raise DivisionByZero error,
if there are no votes, because it'll try to divide by zero
which it can't do so then we're gonna print no votes yet.
Otherwise, if we didn't get an error,
that means this ran successfully,
then we jump into here and we're gonna print that stuff out.
Notice that we're using .2f here
as the formatting guide specifies.
You can use for printing to two decimal places.
I'm gonna leave a link in the resources section
of this video in case you don't know what that is.
All right so this is the more complicated thing so far,
but we're going to analyse it in more detail
as we implement get_poll_and_vote_results.
Finally, randomize_poll_winner takes in a poll id,
prints out the poll options, and then asks for the option id
that is the winner, and then goes into the database
and gets a random vote out of this option,
and then it's gonna print it out.
We're gonna use the database to get the random vote,
so we're gonna learn how to do that later on.
Finally, we have here the MENU_OPTIONS,
so if the user types one,
we're gonna run prompt_create_poll.
If they type two, we're gonna run
list_open_polls and so forth.
But as you can see, this dictionary here
is a mapping of strings, like one, two, and three,
to functions, prompt_create_poll, for example.
It does not run the function.
You would have to run the function
with the brackets like that.
So we're not doing that here,
we're simply mapping the strings
to the functions themselves.
Why?
Because later on in the menu down here,
what we're gonna do is we're going to access
the selection that the user typed, for example, two,
and we're gonna run that.
So this is a little bit of syntax here
that simplifies our menu greatly.
Let's go through this menu function, by the way.
First of all, we're asking for the database URI
using the DATABASE_PROMPT which tells the user
that they can leave it empty if they want
to load from the .env file.
So if they don't type anything, we'll load
from the .env and then we set that
from the environment variables, then we create
the connection to the database, and we use that
to create the tables, then again with the walrus operator,
we allow the user to select an option.
This will be the string one, two, three, four, or five.
Then we go into the menu options and select
the appropriate function using that string.
For example let's say they entered three,
then this piece of text that's highlighted
would return prompt_vote_poll,
so that would essentially replace that,
and as you can see this is how we run the function.
We grab the function from there and then we run it,
passing the connection to it, so that it can use it inside.
Otherwise if they entered something that is not one
of these things, that would give us a KeyError,
in which case we print that an invalid input
was selected and please try again.
At the very end, we run the menu function as well.
So I know this is a lot to take in.
I would really recommend you download this code,
go through it slowly, try to understand it fully.
I just wanted to save you some time,
not have to write all of this stuff
that we've already written before in front of you.
So please do download it and check it out
and once you're ready, we can continue with the next video.
All right, so once you're happy with that,
join me in the next video.
Thank you for watching and I'll see you in the next one.