Python Website Full Tutorial - Flask, Authentication, Databases & More

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
[Music] hello everybody and welcome to another youtube video so in this video i'm going to be showing you how to make a website with python now the goal of this video is going to be to give you a finished product that you can tweak and turn into whatever website you'd like so i want to show you all of the fundamental and important things you need to know about web development with the module that we're going to use so that way you can kind of take this starter or template website and turn it into whatever you want so specifically we're going to cover how you sign up users so how you create new users account how you store those in a database how you log into those user accounts how you log out of them and then how you associate information with a specific user so the example application that we're going to build here is just a very simple notes app so we're going to have it so you create an account and then once you're signed in you're able to add notes or make new notes you can then delete those notes and obviously you can sign out you can log back in on whatever computer you want and you can have access to those notes now this is really simple this isn't super exciting but the point is to give you the knowledge to be able to make something that is more exciting right so this is just very fundamental most apps that you make are going to use like 90 of the code that we're going to right here so it's a really great starter project it's going to teach you a lot about web development and again that's kind of the goal here now keep in mind that we're not really going to be focusing on front end too much i have styled this slightly using something called bootstrap just so that it does look somewhat decent but this is not a front-end tutorial at all you don't need to know javascript for this you don't even really need to know html although i will go over a little bit of html uh and kind of the only prerequisite is you have some fundamental knowledge of python because that's what we're going to be using for the back end of the website so anyways let me give you a quick demo of what we're going to be building here and then we'll actually jump into the code so my website running you can see that we can sign up for a new account or we can log in so let's actually just make a new account i'm going to say tim3 at you know gmail.com is my email my name is tim let me set up a password and a password awesome so i'm going to submit that i've created an account it says my account was created successfully i'm brought to this page that says notes and i can add a new note so i'm going to say hey there you go that's my note i'm going to say you know second note exclamation point add my note now i can delete a note and notice that it gets deleted the other one is still there so now i can log out if i try to go back to the slash home page it's not going to let me because i'm not signed in but now if i sign in so tim3 gmail.com and i type in my password we come back and we can see our notes now of course if we create another account or in fact i think i have another account let's say tim at gmail.com uh you should see that we have different notes showing up here uh okay i i don't have any notes for this account but you can see that there is no notes here so it's showing differently uh yeah that's the basic idea and that's what i'm going to be showing you how to do so again nothing super exciting or super crazy but really important stuff and once you know this again you can go and make whatever you want so hopefully you guys are excited let's go ahead and get started after a quick word from our sponsor before we get started i need to thank typingdna for sponsoring this video typing dna is a developer's first typing biometrics company that provides a low code authentication api that can authenticate users based on the way that they type their authentication api is available for free from their developer plan which provides you with unlimited authentications and end users typing dna works by recording typing biometrics data which consists of timings and durations of various keypress events all new users will provide some baseline typing data when creating their account and then that data can be used to verify their identity in the future this allows users to authenticate their accounts without having to whip out their phone or mobile devices typing dna is built for developers provides seamless identity verification and can help catch fraudsters instantly it works great as two-factor or multi-factor authentication now to illustrate this better let's try typing dna's demo i'm first asked to create a dummy account by typing my email in a made-up password as i type typing dna records my typing biometrics the next time i go to log in it uses this data to authenticate my login as well as typing dna's great api they also have a chrome extension that you can use as an extra security layer get started with typing dna today by signing up for a free developer account from the link in the description all right so let's dive in here the first thing that we need to do is we need to make a folder that's going to store our application so i've just made one on my desktop i've called it flask web app tutorial and i've opened it up here in vs code now feel free to use whatever editor you want i am using visual studio code it's just my preferred one right now for this type of project but you can use subline you can use adam you can use pycharm whatever you want doesn't matter i'm just you know follow along with the steps that i'm doing here so create a folder and then the first thing we're going to do is just kind of set up a little bit of a project directory or kind of some structure here just so that we have all the files defined already so the first thing i'm going to do is i'm going to make a folder inside of this folder i'm going to call it website this folder is going to store all of the code for our website right then i'm going to make a new file i'm going to call this file main.pi and this is the file that we are going to run when we want to start our web server or start our website now inside of website i'm just going to make a few folders we'll talk about these as we get to them the first one is going to be called static and then the next folder inside of website is going to be called templates and then we make a few python files and again we will jump into what all these mean in a second so we're going to say underscore underscore init on your scroll underscore dot pi now this file right here has two underscores before the init and two underscores after make sure you don't only have one and what this is going to do is it's going to make this website folder here a python package you'll see what that means as soon as we use the package parts of it but it essentially means that we can import this folder here and whatever's inside of this init.pi file will run automatically once we import this folder anyways we're going to make a few more files and then we'll be done with kind of the basic setup the first one we're going to do here is we're going to say auth.pi we're going to make another file here we're going to call this one models.pi we're going to use this to store our database models and then lastly we're going to have a file called views.pi this is going to store all of the main views or the url endpoints for the actual functioning kind of front-end aspect of our website anyways that's the basic kind of structure set up here so make sure yours look something like this and then what we're going to do is install some packages so what we're going to do here is we're going to use a module called flask this module called flask is just a super lightweight python framework essentially that allows you to make websites really quickly and really easily if you're comparing it to something like django it's not necessarily as powerful and it's not used as much in production applications but it's really good to know it teaches you the fundamentals of web development and for working on something like that we're doing here building an mvp or even just building kind of a small website flask is great and well that's what i'm going to show it to you because it's just way more simple than django and you can do things a lot faster with it anyways to use flask we need to install the python packages related to it so the first thing we're going to do is we're going to use pip i'm just in a command line here in vs code but if you opened up cmd on windows or terminal on mac you could follow along with this we're going to install flask so we're going to say pip install flask now run this command i already have this installed so you'll see that all these requirements already satisfied but what pip will do is just install a python package for us now if pip doesn't work for you for some reason you're getting pip is not recognized as a command then what you need to do is go to the description i have two videos one for mac and one for windows that will show you how to fix pip now they're not exactly called how to fix pip but they will go through the steps in each video so watch either of those depending on your operating system and it should show you how to fix this command anyways once we've done that and your pip's working now we're going to install another module this is called flask login so flask hyphen login going to install that and there we go now we need one more module as well the last one is called flask and then hyphen sql alchemy i think i spelt that correctly now yeah there we go so pip install flask sql alchemy hit enter and we're going to install that now the modules we just installed or are for logging users in as it said and then sql alchemy is actually a database thing that we can use so it's kind of a wrapper for sql that just makes it much easier for us to create database models delete models um ad models whatever it may be you'll see as we go through the video but install those three things and in case you guys get lost through this video anything's not working there is going to be all of the code linked in the description down below uh so you can check that out on github and and you can copy all that code and everything all right so the first thing we're going to do is we're going to head into our init.pi file we're going to set up our flask application you're going to see how easy it is to do this so we're going to start by saying from flask import flask with a capital f like that then we're going to define a function we're going to call this function create app so we're going to say define create app like that now inside of here we're going to initialize our app so we're going to say app is equal to and then flask and then inside of the brackets here underscore underscore name underscore underscore underscore underscore name just represents the name of the file or i believe it was actually the name of the file that was ran so you'll see but regardless this is just how you initialize flask doesn't really matter what this means just type it in the brackets okay so app equals flask underscore underscore name underscore underscore then what we're going to do after this is we're going to set up one thing that we need for our app so for all of our flask applications we have this config variable called secret underscore key and what this is going to do is this is going to kind of encrypt or secure the cookies and session data related to our website now if you don't know what those mean don't worry about it you don't have to but the idea here is that we just need to type some random string it can be whatever we want it could be a sentence it could be one character that is going to be the secret key for our app now in production you would never want to share this secret key with anybody but since we're just working on kind of the developer side here doesn't matter make the secret key whatever you want obviously i'm showing you mine it's not that important all right so now that we have that what we're going to do is we're going to return this app so we're going to say return app so we have now created a flask application we've initialized its secret key then we've returned it from this function all right so now that we have that what we're going to do is we're going to go to our main dot pi file which is outside of this website folder and we're going to import this website package grab that create app function that we just defined and then use that to actually well create an application and run it so we're going to start by saying uh from website import and then create underscore app the reason we can do this is because website is a python package so whenever you put this init.pi file inside of a folder it becomes a python package which means when you import the name of the folder it will by default run all of the stuff in the init.pi file which means we can import anything that's defined in this init.pi file like our create app so from main.pi we can use create app so we're going to say app equals create app and then we're going to say if underscore underscore name underscore underscore equals underscore underscore main underscore underscore and then we're going to say app dot run debug equals true now this is as easy as it is to run a flask application this will work we will now have a running web server and i'll show you in one second but what this line says is that only if we run this file not if we import this file so main.pi are we going to execute this line the reason you want this is because if for some reason you were to import main.pi from another file and you didn't have this line right here it would run the web server and you don't want that to happen you only want it to run the web server if you actually run this file directly so that's what this line means now what app.run is going to do is it's going to run our flask application it's going to start up a web server and it's going to say debug equals true which means every time we make a change to any of our python code it's going to automatically rerun the web server that's all the debug equals true means obviously you're going to turn that off when you're running in production but for our cases we want that on because that means we don't have to keep manually rerunning the flask web server awesome so this is like the entry point for our app so what we can actually do is i need to fix my python interpreter first in fact i'll show you how to do this in case you're in vs code and you're having some issues with flask if for some reason you know it's saying flask module is not found or you just you can't use flask in fact i'll show you if i run this file notice i get this error no module named flask your python interpreter is probably just wrong now it shows you the interpreter in the bottom left hand corner if you want to change this interpreter which is probably what you want to do you're going to hit control shift and p on your keyboard that's going to open up the vs code command palette and then inside of here you're going to type python and then select interpreter and you can select your python interpreter so the one that i want to use is 3.8.3 again this can be specific to your local machine and the python interpreters you have but now that i select the correct interpreter notice it changed down there and i can run this file so now that i run this file we get some output down here which is saying this is a development server do not use this in production blah blah blah and yeah it pretty much says hey your website is running so now if we want to access our website we need to go to this url right here so 127.0.0.1 port 5000. so what i'm going to do is i'm going to control and click on that that's specific to vs code and it's going to open up this so it says the requested url was not found on the server if you entered the url manually please check your spelling that's fine that's actually good that means our web server is working it just means that we don't have any roots or a home page or anything for our website so that's what we need to add next so what we're going to do now is we're going to create our first website root or yeah i guess our first website root so we're going to go to this views.pi file and inside of this file what we're going to do is we're going to store the kind of standard routes for our website so where users can actually go to so say the login page say the home page all of that kind of stuff actually the login page story is going to go in auth because that's related to authentication but anything that's not related to authentication that the user can navigate to we're going to put in this file so what i'm going to do is i'm going to start by importing flask so i'm going to say from flask import and then blueprint like that and then i'm going to import one more thing as well actually uh we'll import it later i don't need it right now so we're going to say from flask import blueprint now what we're going to do in here is we're going to define that this file is a blueprint of our application which simply means it has a bunch of roots inside of it it has a bunch of urls defined in here that's literally all that a blueprint means it's just a way to kind of separate our app out so we don't have to have all of our views defined in one file we can have them defined in multiple files split up and nicely organized that's what blueprints allow us to do so inside of this file we're going to start by defining the name of our blueprint so i'm going to say views is equal to blueprint now you don't need to name this the same thing as your file but it's usually easier it just keeps it really simple so i would recommend you do that so i'm saying my views blueprint well it's called views now inside of blueprint i'm going to define the name of my blueprint which i'm going to call the same thing as my variable again you don't have to call it this but it's much easier just to call it the same thing so i'd recommend that and then after that you're going to say i'm just going to screen name underscore underscore that's all you need to do we've now set up a blueprint for our flask application so you can ignore the name thing here if you don't understand what that means but that is how you define the blueprint so now what we'll do is i'm actually going to copy all of this i'm going to go inside of my off.pi file i'm going to do the exact same thing except inside instead of views i'm going to call this auth so now i've defined a views blueprint and an auth blueprint and both of these will have different views or different url story defined inside of them so let's go back to views and let's define our first view so to define a view or a route or whatever you want to call it in flask what you're going to do is you're going to say at and then the name of your blueprint so in this case it's called views if we were an auth we would say at auth and then we're going to say dot root and inside of the function here or inside of the uh the brackets we're going to put the url to get to this uh this endpoint or i guess yeah like whatever the root is going to be so in this case we want to define for the home page uh this is the root so slash and then we're going to define a function under here so we're going to say define home now i should have done this before but the point of this function is that this function will run whenever we go to the slash root so whenever we go in our url and we just type in slash so we go to the main page of our website whatever is inside of home is what's going to run so that's the way that you can make this work you define a function you put what's called a decorator above it you define the root and then whenever you hit this root it will call this function so inside of here we're going to do something really basic and we're just going to return some html so we're going to return the h1 tag we're going to say test and then slash h1 what this will do is just return test as an h1 tag it will render this on the website when we go to the slash root so it's as simple as it is of course it will get more complicated this is how you make your first route so now we have these blueprints defined but what we need to do is register these blueprints in our knit.pi so from our app now we need to tell flask that hey we have some blueprints that are containing some different views for our application or some different urls for our application here's where they are so we're going to start by importing these files so we're going to say from dot views import and then we're going to import the name of the blueprint which is views so if i go to views you can see this is what we're importing this variable right here okay so let's go back now we'll do the same thing from auth so we'll say from dot off import off all right so we've got our blueprints imported now what we're going to do is register them with our flask applications we're going to say app dot register blueprint and then we're going to put the blueprint like that and we're going to say url prefix is equal to we're just going to leave this at slash so let me copy this and i'll do the same thing with auth and there we go we've registered our blueprints now the url prefix is saying all of the urls that are stored inside of these blueprints file how do i access them do i have to go to a prefix specifically so i'll just show you with an example because this is the easiest to explain it if i'd put slash auth and then say slash here or auth slash doesn't really matter then what would happen is i would have to go to auth and then slash and then whatever the name of my views inside of here were so if i defined auth dot view like that and or sorry not view dot route like that and then i put inside of here let's say hello if i wanted to access this route since i defined the url prefix as auth i would have to go to slash auth slash hello so anything inside of here will be prefixed now by whatever i define as the url prefix so i don't want anything for the prefix so i just leave it as slash which means no prefix anyways uh hopefully we got that so those that is how you register the blueprints obviously if you had more you would register all of them and you can change the prefix according to what you have but now i'm going to rerun the web server so you can do that by just running this main.pi file i just did it in vs code with a shortcut but not important and now if i run this notice that i get test so i'm getting tests because i went to the slash root so i just went to the home page of my website and what happened was we hit this function right here and we returned this html which was test and we showed that on the web page so that is the most basic way to make a route now i'll show you how to make a few other routes and we'll do it inside of auth.pi so inside of auth.pi we're going to define our login uh log out and our what was the other one we need sign up so we're gonna say off dot root we're gonna say slash login like that and then we're gonna define a function call it whatever you want but i usually just call it the same thing as the root so log in and then here we'll just return some let's go p tag and this is going to say log in like that now we'll define another root so say auth.root we're going to call this one slash log out i'm going to say define log out and then what are we going to return well whatever we want but i'll just return a p tag that says log out okay and then lastly we'll define our sign up so auth.root and then slash sign hyphen up and then define sign underscore up and inside of here we will return p tag that says sign up all right so there we go we have now defined our three routes so now if i rerun the server just you'll notice that the server will crash if you have syntax errors in here so sometimes you do need to rerun it even though you have debug equals true and in fact to show you if i save this notice how the server automatically reruns that's what debug equals true does but yeah sometimes you have syntax errors you just have to restart the server manually so now that we have this if i refresh test is working i can now go to slash sign did i do sign hyphen up uh yep sign hyphen up so that brings me there i can go to log in we see we're at the login page and i can go to log out and we see we're at the log out page so clearly our roots are working it's the most basic part of flask how you set up your roots and your urls all right so now that we have our urls set up what we want to do is we want to start making our pages look a little bit nicer right so i don't really want to just show log in log out sign up i want to show an actual page so how do i render some real html from an html file because it doesn't really make sense for me to be you know putting all the html in a string in python we're not going to do that that's not scalable for our app so now what we're going to do is we're going to go inside of this templates folder and this is where we're going to put what we call our html templates so in flask you could call them html documents doesn't really matter when you render html you call it a template and the reason you called a template is because there's a special templating language that you can use with flask which is called jinga so j-i-n-j-a i believe that's how you spell it this templating language allows you to write a little bit of python inside of your html documents now this is really useful because this means that you don't need to know javascript and you can say render all of a user's notes without using javascript you can display user information without using javascript you can do a bunch of stuff without using javascript based on this templating language now you will see how this works as we really get into this but let me start by defining a new file i'm going to call this base.html so typically when you make templates what you do is you define a base template you can think of the base template as like the theme of your website so whatever you have in this base template is what your entire website's going to look like so usually a nav bar maybe a footer or a header or something like that and then what you will do is you will override parts of the base template with more specific templates now i know this is confusing because i haven't shown anything yet but the idea is that we have one section of the base template which is usually the main content on the page and what we'll do is we'll let our other html documents override that main content so everything else stays the exact same except the main content of the page will change based on what page we're on so anyways let's just start typing out our html document and this is a lot of stuff that you're going to probably have to copy especially the style sheet and the javascript and all of that so do go to the description and open up the github you can type along with me if you want of course but it might be a little bit easier just to uh what do you call it just to copy some of this stuff because i can't really type all of it out anyways we're going to set up our html tags here after our doctype html i'm going to start by setting up a head tag and then we'll set up a body tag so we'll say body and body if you're unfamiliar with html this is just standard practice you need a head tag which has like metadata related to the website and then you have a body tag which actually has the html for the body of the website so the first thing we're going to do inside of our head tag is we're going to define a meta so we're going to say meta and then char set equals utf-8 so just defining the character set that's used for this document then what we're going to do is have another meta we're going to say meta and then name equals viewport and we're going to say that the content is equal to and then width equals device hyphen width so pretty much just saying take up the entire width of the screen and then after this we're going to have a comma we're going to say initial hyphen scale equals 1. now i'm not going to explain this because this is not a tutorial on html you're welcome to look that up if you want but these are just standard things that you almost always have in your head tag then what i'm going to do is i'm going to import what's known as bootstrap now bootstrap is a css framework that has some built-in classes that just make it a lot nicer to style your website again this is not a tutorial on front end or bootstrap so i don't want to get into it too much but what this is right here is a link to what's called a cdn now a cdn is a content delivery network and what that will do is it will allow you to actually load without downloading the file a bunch of custom css and javascript now in this case we're just loading css and we can tell that because this is defined as a style sheet and this style sheet will contain a bunch of classes that we can use for our html elements just to make them look a lot nicer so what you need to do is just copy this again you can get that from the code link in the description you're also welcome to not use this everything will still work if you don't have this css it's just not going to look as nice so we have the two css things to find now so we've loaded our style sheet and we've loaded bootstrap now what we're going to do is we're going to have a title tag and inside of this title tag i'm going to show you the first thing that you can do with jinga which is the templating engine so i'm going to define two brackets like this and then two percent signs now whenever you're using jenga you have a few different kind of syntax options so when you're writing a block where you're writing some pythonic syntax like a for loop or an if statement you usually put them inside of this so you have open squiggly or whatever you want to call it squiggly bracket brace then percent sign and then percent sign and then close squiggly brace now inside of here you can define a bunch of different things you can actually write an if statement in here you could write what else a for loop you can write an expression that you want to evaluate or you can write what's called a block so i'm going to say block title and what this means is i'm defining a block in this base template that can be overridden in a child template so what's kind of going to happen is our children template are going to inherit this base template and any blocks that we've defined inside of this base template they'll be able to change so for example the title of our website we obviously want them to be able to change this so we'll say block title and then we'll say end block inside of this title tag and what this means is now in my child template i can define this same block and when i define this block anything that i write inside of it say like home right there will override whatever is inside of here so if in my child template i wrote say sign up or log in as as the block title it would override what is inside of here so it would remove home and then it would put whatever i typed will make sense as we actually get into the template but this is kind of how you define blocks and what i mean by having templates that you can reuse and defining a base template all right so now that we have finished the head let's go to the body we're going to define a nav bar and then what we're going to do after that is load a bunch of scripts and in fact i'm going to load all of the scripts first so let's load all of these you're going to have to copy these because i can't type them all out and what this is going to load is the javascript related to what do you call it here bootstrap the css framework so bootstrap has some like fancy animations and some just like cool button presses and stuff that use javascript so what you need to do is load in these scripts again just take that from the description from the code so this we load at the bottom of our body tag so make sure it's at the very bottom all other html you're gonna put above it now let's say you're someone who wanted to write your own javascript first of all what you would do if you want to integrate your own javascript into this and i'll just cover this quickly because i know some of you will want to do this is you will put a javascript file inside of this static folder so any assets like images or javascript files or css things that are static that do not change you put inside of this static folder so again images javascript or css files you have to put inside of the static folder now once you put them inside of the static folder you can load them in your html by doing something like this so this is the script that you would write to load in a file called index.js from this static folder so what you do is you write these two squiggly brackets which is another thing in jenga and i'm going to cover this in one second you write url4 then you put the name of the folder which in this case is static and then the file name that you want to load which is index.js now what this url4 function does this is actually a python function okay we'll see it in a minute is it loads the url for the static folder so it just finds that on our website that's what it does now these two squigglies or squiggly brackets i keep calling them squigglies what this means is that we are going to write a python expression so whenever i have two squigglies like this this pretty much means we can write a variable we can write a function we can write some kind of python expression that will be evaluated now there's some rules for the type of python expression you can write in here but that's the idea behind these two squiggly brackets whenever you have them is you can write some python expression that will be evaluated so when i put that inside of here it will evaluate this and there will be some string that is actually source and that's a string will represent the file name index.js so if i made index.js here it would load this file so i put any js that i want inside of here anyways enough on that i apologize about talking that for a long time okay so now that we've done that what we're going to do is go inside of the body and we're going to decide we're going to define a nav bar so we're going to create a nav bar so we're going to say nav we're going to say class is equal to and then nav bar and then navbar hyphen expand hyphen lg now these are all bootstrap classes if you want to see how exactly these work and why i've picked them you can go to the bootstrap website and you can look up navbar you can look up a bunch of different things and it shows you a bunch of really detailed examples of how to create this stuff so i haven't come up with this i've just taken this from the bootstrap website and this will create a nice kind of gray navbar as you saw so now we'll say nav bar hyphen dark so change the color of the nav bar and then bg hyphen dark to make it dark all right so now we have a navbar defined uh that's as easy as it is to make one and now we have to put some buttons on our nav bar so the first thing that i want to put is actually a button that will allow us to expand the nav bar if we're on a mobile device so let's say that our screen is really small and we can't fit all of the navbar items on the navbar then what we need to do is have a button that can expand the nav bar so we actually see all of the different buttons so that's what this is going to do that i'm going to define here so i'm going to say button and then i'm going to say the class is equal to toggle sorry nav bar hyphen toggle so pretty straightforward it's going to toggle the navbar we're going to say the type is equal to a button we're going to say that the data hyphen toggle is equal to and then in a string we're going to say collapse we're going to say that the data hyphen target is equal to and then we're going to put a pound sign which stands for the id of something and then we're going to say navbar because the id of our navbar which we will define in one second is going to be called navbar anyways we have navvar like that then there's some other things that we could add but actually i think this is fine for now okay so data toggle data target okay now that we have that what we're going to do is we're going to close the button tag so slash button and inside of here we're actually going to put the icon that we want to use for this button so we're going to say span class equals and then nav bar hyphen toggler hyphen icon and then we'll just end the span i guess we can just do like that and the span tag so what this will do is this is just going to load an icon for us and then since it ends it's inside of the button tag that's what will show up when we press on this icon it will toggle the button so when you save you should see that it auto formats for you if you're not getting auto formatting in vs code go to the vs code marketplace which is just this thing little cubes here install an extension called prettier if you install this you won't even i think you just need to reload vs code after you install it and then when you save it should automatically format the document for you so that you don't have to deal with all the indentation and all that stuff okay so now that we have that let's define the navigation items in our navbar so we're going to make a div and we're going to say div class is equal to and then collapse and then navbar hyphen collapse then we're going to say the id is equal to navbar so what this is saying is that we're going to have a collapsible nav bar which i will show you once we actually build it and then we'll define the items that we want in this collapsible navbar so let's define another div inside of here so i'm going to say div class equals and then nav bar hyphen nav so this is the actual navigation items we'll end the div and then inside of here we'll define the items that we want so i'm going to say a which is just a link i'm going to say class is equal to and then nav hyphen item and then nav hyphen link meaning that this actually links to something i'm going to say the id of this is login and then you can guess the href so where this is actually going to redirect us to is slash login so that's it for a and then we'll say log in and we will close the a tag all right so now let's copy this and let's put this a few times so we have login the next one we want is sign up so we'll just say the id of this is sign up or maybe we'll just do camel case there and then the page we want to redirect to is sign hyphen up this is going to be called sign up okay after that we want home and we want log out so let's put log out here let's just change this to log out and log out and then lastly we will do home so home home and then we can simply just put slash because that is our home page all right so now we should have a navbar so our server is still running so make sure yours is running you may have to rerun it and if we go and we refresh the page well we don't see anything for logout and we don't see anything for slash right that's because well we've defined this html document but we haven't actually used it so now that we've defined this we want to use this document so this is a template remember we defined this as a template and what we need to do now is actually define some html documents that can use this template because yes we can actually render this template which i will show you in a second but i want to show you how we use this template because the whole idea was this is going to be the base template of our entire website so i'm going to define another template here or another html document i'm going to call this home.html now inside of here what i'm going to do is show you how we extend this template so remember we have this block here this this title block and inside of home what i need to do is i need to extend this base template so i'm going to write the two squiggly brackets and then percent percent and inside of here i'm going to say extends and then base dot html as a string what this means is that this template right here is going to be the exact same as base.html and i can override any blocks that were defined inside of base.html so i can take this block title and i can put this right here and now if i define instead of home well actually sorry this this should be home but let's just make it change so we can see that this did actually work if i make this changed now this is simply going to override the title block from base.html but everything else will stay the exact same so now let's go into views.pi and let's actually render this template so we can see it on the screen so whenever we want to render a template what we do is we need to import the render underscore template function and from our views function we're going to return render template and then just the name of our template so we don't need to do template slash or anything like that we just do home dot html which is the name of our html template and now when we go to this page it's going to render the html inside of home.html now there's a few more things that you can do with templates which we will get to in a minute but that's the basics so let's run this and let's refresh and notice we get some navbar that is collapsible now this icon does not look exactly how i want it to look but notice that when i press this icon all of the the roots are popping up so i'm going to have a look and see what i've messed up here because this should not be uh looking like this right now so there's definitely a change or something that we made a mistake with so i'll be back after i look at that all right so i was able to fix it there was just a few typos you guys probably saw them when i did them but first on line 23 here in the in the html i had navbar toggle this should be navbar toggler that's the class that's why this was looking all weird and then inside of here on line 30 i had spelled collapse wrong so just make sure you spell everything correctly i had collapse and then navbar and then i had the a and the p mixed up so they were like that so obviously it wasn't working because well everything was spelled incorrectly so i spelt collapse correctly now spelt toggler correct and now we should be good to go so now let's load the website here and you can see that as soon as my page gets really small it shows me this button and then i can expand the nav bar to see everything and then if i make it large enough i can see all the items on the nav bar now also look at the title of our website up here it says changed the reason it says change is because we loaded not the base.html template but the home.html template and we over overrode this block here and we called it changed instead of home so that's it that's how you render the template now let's add a block into our base.html template i want to add it right under the nav bar that we can override to actually put content on the screen so what i'm going to do here is i'm going to make a div i'm going to say div and i'm going to say class equals and i'm going to make this a container now the container will just make it such that the content is kind of floating off of the border of the screen it's just it doesn't center it but it just makes it so there's a little bit of padding between it and the nav bar and the edge of the screen and then inside of this container class what i'm going to do is i'm going to define a block i'm going to say block content you can call these blocks whatever you want so name them whatever you want doesn't have to be content and then here i'm going to end the block so now anything that i put inside of here would show up on the screen if i rendered bass.html but it also allows me to override anything in here so now if i take this block and i go to and i just saved and you can see that where'd that put that oh it's just all in line here if i go to h base.html or sorry home.html what am i saying inside of here now i can add an h1 tag and i can just say this is the home page so now that i do this you'll see as soon as i refresh here that we get this is the home page showing up on the home page so now if i go to logout notice that the template's not here because we still are just rendering the html for logout but that's how this works so that's how you deal with templates and hopefully that was somewhat informative all right so now let's show how we can actually render the template for all of our views so we have our homepage but if we go to auth.pi we don't want to show all this boring html we want to show the template for login for log out and for sign up so let's create two more templates let's make one called login.html and let's make one called signup.html assign underscore dot html now we're not going to make one for log out because when you actually press that button it's just going to redirect you somewhere else there's not going to be like a page that it shows i was just doing that for example but you get the idea so let's go to our home.html it wants to literally just copy all of this first of all let's make the title correct in home.html and now for sign up and for login i'm going to paste these in so we'll start in login we'll just change the name to say login and we'll say this is the login page very good now we go to sign up we can change this to sign up and change this to this is the sign up page great so now that we have that let's render these templates so let's go to auth.pi let's import render template and let's use it so now let's say render underscore template and what template are we going to render the login dot html we can copy this and do the same thing for sign up and now we will render sign underscore up dot html all right so now that we've done that let's load so let's refresh let's go to sign up this is the sign up page let's go to login this is the login page and there you go and that is the basics so now that we've talked about that we understand how to use templates let's now discuss how we can actually pass values to templates so one of the great things about this jenga templating language is that we can pass variables or values right to all of these templates and then what that will do is we can actually use those values inside of the templates so let's say i want to pass like it's hard to give a good example right now because we don't have anything meaningful to pass but i'm just going to show you how we can pass a variable to say login.html from our backend right here and how we can display it on the page so on login.html what you can do here is you can quite simply write any variable name that you want so doesn't matter hello could be arg could be string whatever as long as it's a valid variable name type whatever you want so let's just go with text and then i'm going to say that's equal to set it equal to whatever you want so i'm going to set this equal to testing and now that i've done this inside of my login.html template i can access the variable text so if i go to login.html what i can do is i can use my fancy squiggly brackets that denote i'm having a python expression inside of here and i can type the name of the variable that i'm expecting to be passed which is text so if i do this what's going to happen now is whatever is passed to this template with the value text so again text equals testing will show up here uh oops in the squiggly brackets or where they're located so if i run this now and we refresh we see testing shows up so this is how you pass values to your templates you simply define them as some variable and and literally just type it out like this so text equals testing there's a few other ways to do this i'm not really going to go through all of them at least right now but we can also pass multiple variables so i can pass text and i could pass um you know user is equal to and then i'll pass tim so now that i've passed this i can go to my login template and after this i can just say user now that i have user there if i run this we get testing and then we get tim right so i can just show the user now i also could do something like user plus and then s now what this will do is it will interpret whatever the user variable is plus the string s and it will display that so now we get tim's right so there is a limitation to what you can do inside of here you can't do everything you would do in regular python but for the most part you can do like some basic expressions display variables and that's what makes this templating language really useful so that is the basic for that now let's show one more thing with templates while we're at it i want to pass a variable here and we'll just call this boolean and we'll make this equal to true now i'll show you how we can actually write an if statement inside of our template so if we want to write an if statement uh which we'll do here let me just move the block down uh to write an if statement we do the percent type of block and then we say if and then whatever variable we want to check or whatever expression we want to check so in this case i want to see if the boolean variable is equal to true so if boolean is equal to true then what i can do is underneath this block i can write out what i want to do i'll just say yes it is true and then to end my block i can say end block like that or sorry not end block but and if so this is how you write an if statement you do the percent kind of thing you say if whatever the expression is you want to check then end the percent thing and then you write whatever inside of here you want to display if this is true or whatever you want to do if this is true and then you have the end if to signify hey i'm ending this if statement because obviously we can't use indentation to do that so now if i refresh we'll see that yes it is true but if i change is boolean equal to false so let's do that you'll notice that when i run this nothing shows up because that condition was not true so that is how you write an if statement if you want to do an if else then you can do this you can say else and then you can say no it is not true and you don't need to write like end else or anything like that you just have an end if at the very end of all of the statements and now let's run this we have yes it is true and if we change this to false just to get into the else statement here we see no it is not true right so that is how that works that's how the if and else works now i hate the formatting by default for jinga in here like it is kind of difficult to read but hopefully you get the idea that's how you write if and else i'll show you for loops later and then you can do an else if as well i may be incorrect on this i should probably look this up but it's percent percent and i think it's either l if or else if all right so it looks like it actually is just l if so if you say l if and then whatever the other condition is you want to check uh then this works and then if you didn't have an else you would just have the end if at the end but the end if just goes at the very end of all the statements and this works just like regular python so you have if l if else or as many lifts as you want again you don't need the l if you don't need the else and end if goes at the very end anyways let's get rid of these because i don't actually want these and that's just what i want to show you how you pass values to the template all right so now we've learned about templates we know how to pass values to templates we know how to do template inheritance we know how to you know use expressions and all of that inside of the templates let's now create our actual sign up template so i want to actually make the form here because if we design this then we can start working on the back end and we can actually you know create the user account and work with databases and all that interesting stuff so we need to build this form out so first of all we have our blocks defined now inside of our block content we're just going to build an html form so we're going to say form we're going to say method equals post which means when we submit this form send a post request to the back end you don't have to know what that means yet but i will discuss post get and all of that and anyways inside of here let's start by having an h3 tag so let's say h3 let's say a line equals center we want this to be in the middle of the screen and let's end our h3 tag and then let's say sign up so now we have a header for our form that says sign up now i want to have a div so i'm going to say div the class of this is going to be equal to form hyphen group this is just a bootstrap class that we can use i'm going to end the div and inside of this div i'm going to start putting my fields so i want an email address a first name a password and a password too so like your password confirmation and that's what i want for my sign up form so email first name two passwords so let's start by defining a label let's say label this is going to be for our email you just would set this equal to the class that you're going to use for the input field which you'll see in a second let's end our label and let's call this one email address all right now inside of here i'm going to define input field so i'm going to say input i'm going to say type equals email i'm going to say class equals and then form hyphen control again this is another bootstrap class you can look up all these classes from the bootstrap website i'm going to say the id equals email i'm going to say the name equals email notice there's a lot of stuff to type here and the placeholder is equal to enter email uh like that okay and actually let's go lowercase enter email how many times did i spell it incorrectly all right so now we have our input field now what you need to make sure you do here is you need to define a name the reason you need to define a name as well as an id and in fact the id is optional but you should add it because then you have your label linking with your input field which is what you want but what the name will do for us is this is actually what the attribute is going to be called when we pass the information in this field to our back end now that might be confusing but when we submit this form it's going to bundle up all of the information in here it's going to use all of the names of these fields to represent them when it actually sends this information to the backend so we will be able to access the email address by whatever its name is defined as so make sure you define these names and then that you know what these names are so now that we have our first form group defined we're going to copy this and let's do the next one so we have the same div called form group except now we don't have an email we have a first name so we'll just say first name like that change the type to not be email but just to be text and then the class will stay the same the id will go to first name the name should always be the same as the id for our purposes we're going to say first name and then we'll just say enter first name all right awesome let's copy this one and now let's do the passwords okay so we i just copied it twice because we're going to do two passwords so we'll say 4 password one the label is going to be password the type is going to be password the id is going to be password1 and then the name is going to be password one okay and then for here we'll just say enter password and then actually we should probably just copy this one because all we'll have to do is change password one to password two so now uh password i'll just say confirm as the label we'll say instead of password one this will just all be password two and we'll just say instead of maybe instead of enter password maybe we should say confirm password awesome so now we have our sign up form created so now the last thing we need to add is a button so after this div i'm going to add a break line just to separate the button and then what i'm going to do is i'm going to say button type equals submit class equals and then btn btn hyphen primary this is going to make kind of a nice blue button and again these are bootstrap classes that i'm using i'm going to say submit and then slash button so there we go now we have that defined if we go to our website and i was just looking up the the jenga syntax before you can see that and i go to sign up notice this is the form that we get so it looks pretty nice if i press submit you'll see we get something popping up don't worry about that right now but this does indeed work and we have our form now just to be really clear here the reason why i can use all these bootstrap classes is because my base template which i'm inheriting from has all these links right so i'm linking to bootstrap that's what we did in those first steps when we added all these links and we added all these scripts that's why i'm able to use all this nice fancy stuff so i just want to make sure that's clear in case i skimmed over then you guys are wondering you know how it looks this nice it's because we're using a css framework called bootstrap again this is not focused on front end um i just wanted to show you or just talk about what bootstrap is for a second okay now we have sign up so you know what while we're in our html and we're going through and doing all this let's just do the login because it's going to be very similar to sign up in fact let's actually copy this entire sign up form and we'll just modify it slightly in login so for login let's replace all of our content here with this form and now let's remove one of these passwords because we don't need two passwords obviously and let's remove first name and we should be good so now we have email and we have password we'll change the name instead of password1 to just be password and there we go and then we will change the the sign up field here to be login there we go and email that should be all good so i think that's actually all we need for the log in field i'm trying to think if there's anything else we should change maybe we'll change submit to login and that should be our login page so now that we have that let's load the login page and we can see this is what our login page looks like so looking nice awesome that is great okay so now that we have that we've done most of the html that we need to write i hate writing html but we just we do have to do it now we can actually go to python and we can start handling this form so notice actually let me go back to the website here when i press login or i go to sign up and i press submit we get method not allowed this method is not allowed for the requested url so this is a great point in time to talk about http requests so when we're talking about websites uh we use something called http right which i believe is hyper tax transfer protocol i think that's what it stands for something like that and anyways http there's a bunch of different methods that you have with them so you have a get request or a get method a post request or a post method a put request or a put method and then delete and there's a few other ones as well there's an update method and some more now all of these methods can be used for whatever you want but the point of these methods is so that you can clearly distinguish between what type of requests are being sent to your website because what really happens here right is when we go to something in our url address bar we hit some endpoint or some function or some route on our server right and in this case our routes are login login logout sign up you know home all of that now these routes need to know whether we sent them a get request or whether we sent them a post request or whatever it was because based on the type of request they're going to do something differently now typically a get request is when you're just loading a website so when you're loading a web page or you're retrieving information now in our case when we go to this webpage we're retrieving the html that represents this page now a post request usually means that you're making some kind of change to a database or some kind of change to the state of your website or the state of the system or whatever it may be so we would post the fact that we are signing in or that we are signing up and when we post that means we are sending a post request with all of the information in our form so if i go here and let's go to sign up the reason why we were getting that error message is because when we hit this button we are actually by default because we defined method equals post let me find this inside of our form we're going to be sending a request to the url that we're currently on so to sign up that is a post request that has all of the information here so the email address the first name and the two passwords that we typed in it's going to send that to our server so our server needs to interpret that and then respond to us or do something based on that post request so hopefully that's clear but those are some of the main http methods and that's kind of how they work a get request is retrieving information a post request is updating or creating something then you have update delete put a bunch of other http requests which we're not going to use in this video but you're welcome to look up and are pretty straightforward in how they work so let's go now and let's make sure that we can actually accept this post request so if i go to views.pi or sorry opt.pi mybad now what we want to do is we want to make sure that login and signup are able to accept post requests so to do that we need to define something inside of our root that says methods and is equal to a list and inside of here we're going to write the strings for the type of requests that this route can accept now by default we can only accept get requests but now when we add get and we add post here we are able to accept get and post requests so let's copy this let's put this to sign up and now what this means is we are able to accept get and post requests from both of these routes so if i go and i refresh and i press submit now notice that it just reloads the page right because we sent a post request and it simply returned to us the rendered template again right that's all that happened when we sent the post or we sent the get request so to be clear when i go to this url from the url bar this is a get request when i press this submit button this is a post request because i'm sending the information to the server all right so now let me show you how we get the information from this form on the server now what we do is we need to start by importing something called request at the top of our flask application so if we want to get the information that was sent in this form we can do the following we can say that data is equal to request.form so this request variable is whenever you access it inside of a root it will have information about the request that was sent to access this route so it will say the url it will say the method it will say all of the information that was sent and in this case we can access the form attribute of our request which has all of the data that was sent as a part of a form so here i can say data equals request.form and then i can print data now you're going to notice that we may get an issue here because i'm doing this regardless of the fact if i'm sending a get request or i'm sending a post request if a get request or post request comes in we're not differentiating between them we just do the same thing all right so now that i have this line sorry i got a little confused there i'm going to go to login and what i'm going to do is i'm going to send some information so i'm going to say tim at gmail i'm just going to say 1 2 3 4 and i'm going to press log in now notice it should print the data here so if i log in then notice here we get printing out an immutable dict object or mutable multi-dict that has the email which is tim gmail one or tim gmail and then password1234 so that is how we access information from the server here we can look at the request.form attribute and if we sent any data or there was a form attribute then we print it out now the one thing to keep in mind here is that this is only going to work it's only going to give us data if we actually send a form right so if i if i go here and i just refresh this and i look at my immutable dictionary we don't have any data inside of it the reason we don't have any data inside of it is because we sent a get request and while there was no form attribute in that get request we didn't we didn't have any data we sent with the get request but when i send the post request and i press log in we get our email and we get our password so hopefully that's clear but now let's look at how we can do this on the sign up page how we can get user's information and store that in a database and create their user account so the first thing we want to do i'm going to delete this from login i'm going to go to sign up i want to differentiate between my get request and my post request so to do that i'm going to say if request.method is equal to an all capitals post then i want to do something specific so if it's a post request do something if it's a get request do something else that's what i'm checking so inside of here the first thing i want to do is get all of the information from my form so i want the email first name and the two passwords i'm going to say email equals and then request dot form and then you use this method called dot get to get a specific attribute or specific value so we're gonna get email we're then gonna say first name equals request.form dot get and we're gonna get first name then i want password so i'm going to say password is equal to request.form.get and i want password1 so let's call this password1 and then we want password2 so we'll do the same thing password2 equals request.form.get and then password2 awesome so now we're going to get all this information so we will get the email first name password1 and password2 from our sign in form then what i want to do is i want to start by making sure that this information is valid so if this information is not valid then i don't want to create a new user account but if it is valid then i do so let's just do a few very basic python checks here let's say if the len of email is greater than let's say four characters then we're all good to go right we'll say if it's less than four characters then we will kind of tell the uh the user that there's an issue i'm not going to do that this second but i'll show you how we do that then we'll say l if the the len of first name is less than two so if it's only one character or it's zero characters that's no good but we'll do something else if that's the case and then we'll say l if password1 does not equal password2 then we want to tell the user there's an issue and then maybe we want to have like a length on the password we'll say l if the len of password1 is less than seven characters then there's an issue otherwise we'll say add user to database so if all is good we can add the user to the database so what i want to show you now before we actually go ahead and do this is how we can kind of alert the user if something went wrong so they're sending us this request and saying hey i want to make a new account and we want to check to make sure all this information is valid and if this information is not valid well we should pop something up on the screen and tell them hey no that's no good you can't do that now this is where we get into something called message flashing which is a really cool part of flask i think you can do it in django too although i'm not sure so what you're allowed to do or i guess what you can do is you can flash a message on the screen using flask it has like some built-in functionality for it so to flash a message what you do is you import something called flash and then you use this function whenever you want to flash a message so on 25 if i want to flash a message that says hey you know your email is too short then all i do is i say flash and i say email must be greater than four characters okay and then i can define a category for this flash so if this is like a successful message then what i would do is the category equal to success and if this is a failure message or a message where there's an error then i would use the category error now you can name these categories whatever you want like they're up to you you can name them e you can name them one you can name them two so long as you know what they mean because we're going to use these categories to display these messages in a different color anyways let's flash a bunch of messages here so we'll flash here and now we'll say first name must be greater than two characters uh or must be greater than one character story and this one really should be three that's correct then after this for password we'll flash hey your passwords don't match so let's say uh passwords don't match and i need to escape this so just use an escape character like that then we'll do another flash and we will say that password is too short password must be at least seven characters and all these are error messages right and then otherwise uh let's flash a successful message uh now we will actually have to do something else here we'll say account created exclamation point category equals and then success all right so there we go we flash a bunch of messages now if this does work i'm just going to remove this pass and this is only if there's a post request right and then regardless at the end we return the signup.html template so now let me show you how we actually see these flashed messages because if i just run this right now these aren't going to do anything nothing's going to happen because we haven't displayed these messages so i'm just going to rerun the server i'm going to go into my base.html template so let's find that here i'm going to write a kind of block of code uh where it's based i meant to load this up here that is going to actually let me show these flashed messages so underneath the nav bar but above my main content is where i want to show these messages so i'm going to write a for loop and i'm going to do the following or sorry i'm going to write you'll kind of see i just have to write it out and then i can discuss i'm going to say with messages equal to get underscore flashed underscore messages and then we're going to say with underscore categories is equal to and then a lowercase true notice this is lowercase not capital this is a a difference in jenga you use lowercase capitals right all right lowercase capitals use lowercase uh for the first letter for true and false so we're going to say get flash messages with categories equals true and then we're going to end the with statements we're going to say like that and with now what this is going to do is just going to define a variable called messages which is equal to get flash messages this is a function that we can just write out because it's built into flask and this is going to get all of the messages that we have flashed sometimes there may be multiple and then we will display or we will get those messages with their categories sorry now what we will do is we will loop through all of the messages because we could again have multiple messages and we will display them on the screen so i'm going to start by saying first of all we need to make sure we actually have some messages right so if messages and then i'm going to end this if so if we do actually have messages if it's not just empty then what we're going to do is we're going to loop through them so we're going to say for message in messages just like in regular python except we don't need the colon at the end and then we're going to end the for statement we're going to say n4 like that now what we'll do inside of here is we will write some html that will just display whatever the message is so i'm going to write a div i'm going to say div and then class is equal to this is an alert so in bootstrap we have something called alerts i'm going to say alert and then alert hyphen danger so this is an error message and then this is going to be a dismissible alert so alert hyphen dis misable like that and then we're going to say fade and then show now what this will do is it will fade in the alert it will allow us to dismiss the alerts and then it will be shown by default then we will say slash div and one more thing we need to have the role of this equal to an alert okay so that's our div for the alert now inside of here we need to actually show the message so we're going to use two braces we're going to say message the reason we're doing that is because we're accessing this message variable right here then we're going to add a button that will allow us to dismiss this alert so we're going to say button we're going to say type is equal to button and we're going to say class equals close we're going to say data hyphen dismiss is equal to and then you guessed it alert then we're going to end the button and inside of here we're going to put a little icon that will allow us to actually uh like show something nice for this button so we're going to say seban area hyphen hidden equals true and then we're going to say this thing so the ampersand sign uh which is right here and then times semicolon and then slash span now this is just a special character that is gonna be like kind of a fancy x uh and it's just gonna show it in this button uh i can't really talk about it much more than that that's that's just what it's going to do now this however though is what we want to show if we have the category that is equal to error so we have two types of alerts right we have an error alert and a successful alert so if we want to show that we had an error then we probably want to show it in red right which is what alert danger means and then if we had one that was successful well we want to show it successfully we want to show it in green so i'm going to copy this exact thing i'm going to paste it again but i'm going to change alert danger to alert success now what this means is literally change the background color to green that's the only difference between this and the other one but now what i will do is i'm going to have some if statements inside of here that say okay well if the category of this message was what do you call it error then what do we want to do well we want to show the error if it is success we want to show the successful message so i actually need to change this to say for category comma message in messages so we'll loop through both of the things that we need and then we'll do an if statement right here so we'll say if category is equal to and then the string which is uh not danger but error then we will show this so now we need to put our else statement right here so percent l so pretty much if you don't have error we'll just show the success one and then we need to end our four so we can do that right here and four so i know this is a lot of code but this is how you show the flashed messages so we start with the with messages equals flashed with categories equals true we say if we have any messages so if this is not equal to none then let's loop through all of them let's check if the category of our message is error if it is then let's display an error message box so alert danger otherwise let's display the success message box and we'll throw whatever the message actually is in that message box and then why do i have two and fours sorry one of this should be and if my about on that uh and there we go that that's all we need to actually show the flash messages now since i put this in the base template this will now work on any of our pages so if we flash flash messages it doesn't matter where we flash them they will always show up because this is on the base template so if i save this it does this you know crazy formatting which i hate that makes it way harder to read but you get the idea that is how you do this and if you missed any of this you can just go to the code in the description all right so now let's try this let's refresh and let's submit now notice that when we submit the first thing it tells us is email must be greater than three characters so let's go back to the code alright so we're here and we can see in sign up the first thing we check is if the email is greater than three characters or not no it obviously wasn't uh so that's why we got that message so now let's enter an email let's say tim at gmail let's press submit and then says first name must be greater than one characters or i guess i should just say one character let's actually change that we get the idea now it's showing us these flash messages now let's uh input some valid stuff so tim [Music] gmail.com tim one two three four five six seven just so that we get past that limit and now it says account created now obviously we didn't actually create the account but that's the message that's flashed if you press the x button it closes the message so there you go that is how you flash messages now at any point in time in your program now that we've implemented that code in base.html if you ever want to notify the user of something just flash a message and then choose whatever category you want to show so error success and you're welcome to implement more categories as well if you wanted to show like a gray message or stuff like that you just have to write some more html for that okay so now that we have that let's talk about the database aspect so we know what a flash message is we know to get information from the form let's do something with this this info so this is where it gets a little bit more complicated but still nothing crazy by any means we're going to go into our init.pi file actually we're going to start setting up our database so the first thing that we need to do is need to import sql alchemy so we're going to say from flask underscore sql alchemy import and then all capitals sql or sql and then alchemy now this is what we're using for the database and the first thing we need to do is define a new database we're going to say db equals sql alchemy and just initialize it like that underneath we're now going to pick our database name it's going to say database our db name is equal to database.db all right so now we have the name and we have the database object this is the object we're going to use whenever we want to add something to the database create a new user whatever we're going to use this object you'll see how this works so once we've done this we now need to tell flask that we are in fact using this database and where the database is going to be located because we actually need a file to store all of this in we're going to be using sqlite 3 to do this so we need to say app.config and then we're going to say this is sql alchemy i always spell this incorrectly underscore database underscore uri is equal to and then we're going to do an f string this is only going to work in python 3.6 above by the way if you this f string if you don't understand the f string i'll explain it in one second but we're going to say sqlite and then colon three slashes and then inside of brackets db underscore name so what i've just done here is i've said okay my sqlite or my sql alchemy database is stored or located at this location so sqlite3 our sqlite colon slash slash and then whatever the database name is which in this case we're calling database.db you can call it whatever you want but what this will do is it will store this database in the website folder so inside of the directory that this init.pi file is in so we're just telling flask where this is located now what we're going to do after this is we're going to initialize our database by giving it our flask app so we're going to say db dot init underscore app like that now again what this is going to do is just going to take this database that we defined here and and pretty much tell it hey this is the app we're going to use with this database this flask app that we just created so now that we've done that what we need to do is define some database models or tables right if you've worked with a database before then this is probably familiar to you but if we want to store something in our database we need to kind of define the schema of what that object is going to look like so anyways hopefully this is clear uh yeah the f string if i didn't explain when you put the f beforehand you can use these squiggly brackets and whenever you write inside of the squiggly brackets it can be like python code and it will be evaluated as a string so this is just going to evaluate to sqlite colon slash database.db because that's our db name all right so now let's actually go into our models.pi file and this is where we're going to create our database models i'm going to do them both right now just to make things simple but we want to have a database model for our users and we want to have a database model for our notes because we're going to be storing notes for this app right so i'm going to say import dot or sorry not import dot from dot import db now what i'm doing is i'm importing from the current package which is this website folder the db object now not db name just db notice that when i go to init.pi i have db defined this is what i'm importing because this is in a net dot pi if i say import from dot where even was i from dot import db that means from this package and i can access anything in the nit top pi import db so that's what we're doing when i say from dot that would be equivalent if we were outside of this directory directory from saying from website import db okay so now that we have that what we're going to do is we're going to say from flask underscore login module we've yet to use yet import like that user mixin now this is just a custom class that we can inherit that will give our user object some things specific for our flask login now you don't really need to worry about what this is but flask login is just a module that kind of helps us log users in and well our user object needs to inherit from user mix in which is what i'm importing right here anyway so we're going to do is we're going to define a class and whenever you want to make a new database model so you want to store a different type of object you're going to define the name of the object usually this is not plural you're just going to make it singular and then you're going to have it inherit from db.m so db again was that sql alchemy object that we created now for our user object in particular this is not for any other objects just for the user object what we're going to do is also inherit from user mixin so now inside of here what we will do is we will define all of the columns that we want to have stored in this table so we're essentially defining a schema or a layout for some object that can be stored in our database we're saying okay this object is going to have what well it's going to have an id it's going to have an email it's going to have a password what else do we want to store on it now it's just easier for me to do this all at once but let's jump in so i'm going to say id is equal to db dot column and then i'm going to define the type of column so for all of our objects we need to have what's known as a primary key whenever you create an object in a database we need some way to uniquely identify this object so for all of my users you know they could potentially have the same email now we're going to make it so you can't have that but let's say they have the same first name we need some way to differentiate them so we have something called a primary key which is a unique identifier typically an integer that represents our object and it's completely unique no other object in this database table in this database table sorry will have the same id so i'm going to say db dot integer this is the type of column and then i'm going to say primary key equals true so our id is our primary key which again is the unique identifier now for all of our objects we will have an id sometimes you call it something else but id is what we're going to use next what else do we want our user to store well we want to have an email for our user we want to have a password for our user and then we want to store their first name so i'm going to say email is equal to db.column you're almost always going to have db.column except for some specific cases and then you're going to define the type of the column so for our email well this is going to be a string the maximum length of this string we're going to say is 150. so whenever you define the string you need to pick a maximum length for it we're just going to go with 150 you can make it larger if you want doesn't matter then we're going to say unique equals true when we define this this means no user can have the same email as another user so it is invalid to create a user that has an email that already exists then we're going to say password is equal to db.column and inside of here we're going to say db.string and we're going to again define how long we want this to be and i'll make max 150. then we'll say our first name like that and honestly this should be camel case sorry is equal to and then db dot column and then we'll say db.string and make this 150 characters okay so now that we've done that we've set up our user model so we are going to store all of our users in a schema that looks like this so we can have multiple users obviously and all of them are going to have an id an email a password and a first name that's what this defines right here next what we're going to do is we're going to set up a an object called note so i'm going to say class note or sorry class called non-object this is going to inherit from db.model and this is going to be a much more general schema or much more general database model now in case you're confused a database model is just like a layout or a blueprint for an object that's going to be stored in your database so when i say user that means all my users have to conform to this right here when i say note this means all of my notes need to conform to what i have right here you're just telling the database software that like all notes need to look like this all users need to look like this so you know all your information is always going to be consistent anyways this user one was a bit different right because we inherited from user mixin i'm not going to really i don't want to go in too much depth on what this means but it's just to do with the fact that we're using this flask login module if we weren't using flask login we were doing this completely from scratch by ourself we wouldn't inherit from this class anyways now we have class note inherits from db.model this is a much more general class what we're going to do is define very similar things to what we defined in users so first we're going to say id all our notes need to have unique id is db.column db.integer and then primary key equals true now it's worth noting that by default when you add a new object you do not need to define its id it will automatically be set for you so the database software is smart enough to just increment the ids so that they're always unique and the next id inserted will simply be id plus one of the last id that was inserted in the database all right now for our note what do we want to store well we want to store the data associated with the note now you could call this text too doesn't matter and i'm going to say this is db.com db.string and our notes will be at most let's go 10 000 characters long now you know someone could make a note longer than that but let's just go with 10 000 characters and then we want the date that this note was created at so db.column db dot and then date time and inside of date time i'm going to say time zone equals true so it's going to store time zone information as well and then lastly i'm going to say the default value of this field is going to be equal to and i need to import something now i'm going to say from sql alchemy dot sql you will already have this if you imported or sorry if you installed flask sql alchemy and i'm going to import funk now this is very strange but essentially what i'm doing here is i'm making it so that we don't need to specify the date field ourself we just let sql alchemy take care of this whenever we create a new note it will automatically add the the date for us now we do that by saying the default is equal to func.now what funk does is it just gets the current date and time and it will just you know store that as a default value for our date so whenever we create a new note object it will just call func it will get whatever time it is and then it will use that to store in the date time field and it will store the time zone information of this date time object as well alright great so we have that next we are going to actually allow us to associate this a note with our user so all of our notes must belong to a user right now this is the point where i'm showing you how you associate different information with with different users if we have notes and we want to have notes that are being stored for each user like each user has multiple notes we need to set up a relationship between this note object right here and our user object now we do this in the form of a foreign key so a foreign key essentially is a key on one of your database tables tables that references an id to another database uh column so a foreign key is essentially a column in your database that always references a column of another database so in this instance for every single note we want to store the id of the user who created this note so i'm going to say user underscore id is equal to db dot column and then inside of here i'm going to say well what is the id field for my user well it's an integer so i need to match this because this user id column here or field is always going to store an id of one of the users so i'm going to say db.integer and i'm going to say db dot foreign key did i spell foreign incorrectly i did foreign key and then here we're going to say user dot id now this is where i need to kind of go into some more depth here we're saying that the type of column is integer and by specifying foreign key what this means is we must pass a valid id of an existing user to this uh field or to this column when we create a node note object this is what we call a one to many relationship where we have one user that has many notes now i don't really want to get too much into databases this is something that you you kind of need to look up on your own and learn about that's not the purpose of this tutorial here but when you have a one-to-many relationship you have one object that has many children now in this case we have one user that has many notes so what we do is we store a foreign key on the child objects that reference the parent object so now every time we have a note we can figure out which user created it by looking at the user id and again this db.foreign key enforces that we must give a valid user id to this object otherwise we cannot create it because we have a relationship between the user and the note now user.id where am i getting this from well the name of our tables by default are underscore so in python we use capitals for the classes because that's the convention but in sql this user class here will actually be represent represented by user so that's why i'm putting user here with a lowercase u now id that's the field of this user object so i'm referencing the id field if the primary key was represented by say like name or email then i would do email but you just put the the primary key of the other object that you're referencing where other table you're referencing in this case user.id great so now we have that and now what this means is that from each note we can reference who created it but we don't just want that we want from all users to be able to find all of their notes so what we need to do now is we need to set up a field on our user that says notes and is equal to a db dot relationship with what well with the note table now what this will do is it will pretty much tell flask and tell sql alchemy do your magic and every time we create a note add into this user's notes relationship that note id so this relationship field will really be a list and it will store all of the different notes now that's not exactly how it's going to be represented but we will be able to access all of the notes that a user owns or has created from this notes field by denoting this db.relationship and then putting the name of the the other table that we're referencing now notice that here it's capital so you know it's not very consistent but you do need capital for this one don't ask me why it's just the way that sql alchemy works when you do the foreign key you have lower case and when you do the relationship you're referencing the name of the class which is obviously capital so hopefully that's clear i know i just went through a lot there um there's just so much to talk about when it comes to making websites so uh you know it is difficult to go through everything in absolute depth but this is the two database models that we're going to have now if we wanted to have another one we would just do the same thing so we wanted to have say you know maybe you could store videos on the platform or maybe you store reminders or whatever we would just set up another class so it's a class reminder it would inherit from db.model we would define all of the fields that we want to store for this reminder class and you can look these up on flask sql alchemy and then we would add the foreign key to our user now this foreign key that i showed you is only when you have a one-to-many relationship so one user having many notes now if you had a many to one that means you can have like one note belonging to many users right so there's different relationships you have between objects i just showed you one to many which is the most common you can also have one-to-one and many to one so you will have to look up how those work but there's lots of documentation online anyways we should finish that now we did the database now what we need to do is we need to actually create this database so we've set it up we've defined what it will look like but we need to create it so we're going to go inside of a nit.pi we're going to write a little script that's going to check before we run this server every time if we have created the database yet so the first thing we're going to do is after we register our blueprints here we're going to say from dot models and we're going to import our user and we're going to import our note now you could just import models like you could just just say import models like that like either works doesn't matter um and sorry it's not going to be models it's going to be dot models just like dot views and dot auth because we're doing the relative import the reason we import this is not because we're actually going to use anything it is because we need to make sure that we load this file and that this file runs this models.pi file runs and defines these classes before we initialize or create our database so we import the models file so that it defines these classes for us and then we can go ahead and create our database so i'm going to write a function i'm going to say define create database and this is going to take app now what this is going to do is it's going to check if the database already exists and if it does not it is going to create it because if it does exist we don't want to override it because it has data in it already so we're going to go to the top of our program and we're going to say from os which stands for operating system import path and then what we will do is we will use this path module to determine whether or not the path to our database exists we'll say if not path and then inside of here we're going to say website assuming you called your folder here website if you change the name you'd have to change that and then plus db underscore name uh and sorry this is path dot exists so if path dot exists website plus db underscore name then db dot create underscore all app equals app and then we will just print created database exclamation point then we'll run this function so we'll just do it here create no not create app create database and then pass app so the way this works we use the path module check if the database exists if it doesn't exist we create it that's what db.createall does the reason we need to pass app is because we need to tell flask sql alchemy which app we're creating the database for because obviously if it's a different app then things are going to change and this app also has the sql alchemy database uri on it which tells us where to create the database so i'm going to save that and now we will have actually set up this flask sql alchemy all right yeah whatever database whatever you want to call it so now let's run this uh and from import.models what's wrong with import.models i might have to do from.models import sorry and then user actually it's not that it's import dot models as models okay so the reason i got this error it was saying i couldn't import dot models is because we need to if we have a relative import rename what we've imported this as is something that doesn't start with a period because i can't reference like i can't do dot models dot user i can't reference the user class like that because i can't start a variable with a dot so we just need to change the name that we import this as to something that doesn't start with a dot so models and now this should work so import dot models as models because it's a relative import so let's try this and still an error right we might need to actually just do this from dot models import user and import what do you call it so i always get we have note so i guess i can't even do what i just did i thought that was going to fix the issue i don't often run into this but i believe if we're having a relative import i guess we just have to use from and then import all of the classes or whatever we want from that we also i could get guests could import star which just means import everything let's in fact let's do that so let's run this and now define create app uh there's an issue with this what's it saying line nine star only allowed at module level great okay so let's not import star i can't get past the damn import statement let's import user and let's import what else was it note okay i apologize about that guys but issues do happen yeah anyways let's run this down okay so all is working looks like this is the way we're going to have to import it if any python experts are there in the in the comments please let me know why that wasn't working and now let's go and refresh okay uh okay well that was the post request that refreshed anyways all is working on the website login log out sign up home and now look we have a database.db created in our directory awesome so we've now created these tables now that we've done this we can actually do some more interesting coding we can get out of this init.pi file and we can start using our our sign up method right here our signup function to actually create an account so in our else statement so assuming all of this stuff is correct what we're going to do is create a new user so this is actually super simple uh what we're going to do is we're simply going to say user or new underscore user is equal to user like that we're going to say the email for this user is equal to email we're going to say that the first name of this user is equal to the first name and then we're going to say that the password is equal to and then we're going to hold off for a sec because i need to import a few things so what i'm doing is i'm creating a new user this user is the user that i defined in my models.pi file right so user right here so what i need to do now inside of auth.pi is need to import that so i'm going to say from dot models imports user so now i have the user imported so now i can actually you know use this right here but what i also need to do is i need to import a few things from flask login that are going to allow me to hash a password so i'm going to say from and then this is work zuberg or work zug i don't know how you say this dot security import generate password hash and check password hash so if you're unfamiliar with the hash essentially it is a way to secure a password such that you are never storing a password in plain text so you never want to store a password as what the actual password is you want to somehow kind of change that password or convert that password into something that is just much more secure now we call that a hash now i need to discuss what a hashing function is to explain a hash but a hashing function is a one way function such that it does not have an inverse now what does that mean well if we have a function x maps to y let's say we have a function f of x equals x plus one okay this is a function that does have an inverse now the inverse of this function or what is an inverse well inverse means given y which is x plus one like x plus one would be y you are able to get back to x so the inverse of f of x is f of y is equal to y minus 1. now what this function does is it takes y and it maps it to x the way this works is that if i know x plus 1 is what gave me y then i know i can find what the original x was by just subtracting 1 from whatever this function gives me right so if f of x if i call f of 2 and that gives me 3 then i can say f of 3 and that gives me 2 then this function here let's just let's just call this g sorry or f prime then f prime at 3 giving me 2 is the inverse of f x now there's a lot of math going on here but hopefully you get the idea essentially if you're given the output you can find the input that's when inverses now a hashing function is a function that has no inverse that means that you can generate a hash with it so given some x it will always generate the same value y but given a y you cannot find what the x was now the reason this is important is because when you generate a hash what you do is you pass the password to this hashing function as x and it spits out some y but with that y you can never find what the original password was you can only check if the password you type in is the correct password by running it through the same hashing function so if i run my password that i'm you know typing in to try to sign into account through a hashing function and it equals the hash that means the password was correct but if i'm just given the hash there's no way for me to check what the password is so hopefully that's clear it's hard to explain without like writing anything out i'm just you know typing in this editor but the idea is that you're never storing the password in plain text and if you hash the password you can never return to the original password you can only check if the password you type in equals the hash that's stored that's how it works so when we store our password the whole point of this was to say we're going to store it with a hash we're going to generate password hash and we're going to pass the password 1 here we know that password 1 and password 2 will be the same so it doesn't matter what we pass then we'll say the method is equal to and then shot 256 which is just a hashing algorithm uh you can pick a different hashing algorithm if you want but just go with shot 256 if you don't know which one to choose there's all kinds of videos online if you're more interested in hashing it's actually a pretty interesting thing so anyways now that we have that password defined what we need to do is we need to add this this account to our database so we've defined the user but if we want to actually add this to the database what we need to type is the following db.session dot add new user what this means is add the new user to the database then what we need to do is we need to make a commit to the database so we need to pretty much say hey we've made some changes in the database update it we do that by saying db.session.commit so now that we've done that we're all good and this will actually create a new user for us so after we create the new user we will flash the message saying hey account was created awesome success and then we are going to redirect the user to the home page of the website because after they create their account we should sign them in and then they should be redirected to the homepage so what i'm going to do now is i'm going to import from flask something called redirect and something called url4 so i think these are pretty intuitive to understand what i'm going to do with them but what we're going to do after we flash this message in the the else statement here is we're going to return a redirect to the url for the home page that's what we're going to write so we're going to say return redirect which means redirect us to another page and then we're going to say where do we want to redirect well we want to redirect to the url for views.home now the reason i'm doing this is because views is the name of my blueprint so we go here we have views home is the name of my function so i'm finding what url maps to this function now i could just put in a slash like i could redirect uh to just a slash here and this would work the same but that means if i ever changed the url uh and oops this sorry this should not be in a string this url for sorry that means if i ever were to change the url for that home function i would need to come in here and change this so it's better to use url for and just do the blueprint name and the function name that you want to go to that way if the root for that ever changes this will pick it up so that's what this do this is doing is just finding the url associated with this function all right so now that we have this what's going to happen is we're going to actually create the account and then it's going to redirect us to the home page after we send the post request from signing up so let's create an account let's actually i need to rerun the web server here so let's do that and now if i go here i will refresh i will go to sign up and let's make an account so let's say tim gmail.com let's go tim make our password pretty basic does need to be at least seven characters and we'll press submit and it says first name is an invalid keyword argument for user okay interesting so that means that we must invest something up in our models file so let's go to models up high and what does it say here uh first underscored name that's why okay so now let's go to views.pi or auth.pi and i realize that i've just i've just named this argument wrong so i need to say first underscore name equals first underscore name uh and did i ah so let's go over here okay so i just changed this to be first underscore name instead of the camel case first name which i should have done anyways that was just a habit i guess to do it the other way uh but yeah we have first underscore name equals first underscore name and in case i wasn't clear here you just define all of the fields that you have in models.pi and then you set them equal to whatever they're equal to right which is what we did anyways let's run this now uh let's just refresh because this should just resubmit the post request and then first name is not defined where is this uh oh l if len of first name of course we we need to change this so let's go first underscore name okay and let's refresh continue and now it's the issue db is not defined of course db is not defined we didn't import db so these are the kind of issues you run into all right so now we have to import db so we're going to say from dot import db great and that's again from the init.pi file we already showed that previously okay so now we have everything imported that we needed uh hopefully this should work let's refresh and send again and there we go account created that means we actually did create this account and it redirected us to the home page so now what we need to do is we need to actually kind of signify the fact that a user is signed in and has created an account we need to let a user log in right or sign in now that they have the account so let's do that let's handle the sign in form now or the login form so inside of here i'm just going to start kind of coding some stuff out i'm going to say if request.method equals equals post so if we are actually signing in and we're not just getting the page we want to get the email and the password from the form so we're going to say email equals request.form.get and then we want the email and then we're going to say password equals and then request.form.get and then of course we want the password all right now what i'm going to do is i'm going to check if the user email that we've typed in here or that was sent to us in this form is valid if we actually have a user that has that email in the database now this is going to show you how you actually kind of query the database and look for specific entries so i'm going to say user is equal to user which is the database name right and then dot query dot filter by this is what you do when you are looking for a specific entry in your database or a specific user whatever it is and you want to look by a specific column or by specific field so i'm going to say email equals email now this means filter all of the users that have this email right here that's what i'm saying if i was looking by id i'd say id equals and then whatever the id was okay so email equals email and i'm going to say dot first what this will do is return the first result now there should only be one result if there is any results because we might not have a user that has this email but if we do we should only have one because each user must have a unique email so what we'll do now is we'll say if user so if we did actually find a user then we need to check if the password they typed in is equal to the hash that we have stored on the server so we're going to say if check underscore password hash we're going to pass the user.password which is whatever user we found here whatever their password is we access with dot password if i wanted to access their email i would say dot email if i want to access their name i would say first underscore name so we say user.password and then password which is the password that we got from the form so if this is the case if these hashes are the same which is what this function will do is just compare it with it will hash this password and then check it against this password essentially if that's the case we logged in successfully so let's say flash and then we'll say logged in and then successfully like that okay and let's do an exclamation point category equals success okay now if that's not the case then we need to make sure that we tell the user hey no you didn't log in that was incorrect wrong password whatever so if the password is wrong then let's flash a message and let's say incorrect uh password like that maybe try again okay and then category is going to be equal to error and then if the user doesn't exist then we need to tell them that hey there was no user with that email so we're going to say flash and then email does not exist and then category equals error okay and that's all we need for this but before i do this it just reminds me one thing when i was writing this we need to make sure that when we sign up a user that that user does not already exist right we need to make sure that the email they're using doesn't already exist or a user doesn't already have that email so the first thing we're going to do inside of here is the exact same thing we just did here we're going to say user equals user.query.filterby email equals email.first i'm going to copy that it's going to be our first line and now we'll change this to an alif and we'll go actually we'll just go user and then we'll say if user so if there actually is a user then we'll just tell them hey no this email already exists okay so now we will say the category equals and then error great so that's going to make sure uh query the user make sure that we're not signing up users with the same yield okay sweet so now we have that so the login and signup forms are pretty much done let's go back to the website after i rerun this here i guess it crashed for some reason and let's give this a refresh so now let's let's just us log out doesn't do anything but we can go to login and let's see if we can create a new account with another email and then sign it so let's try with tim gmail.com which i think is an email that already exists in fact let me just submit this and notice it tells me already email already exists so great that's working all is good so actually let's sign in as that user so tim gmail.com i'm going to type an incorrect password and incorrect password try again awesome so now let's try again team gmail.com one two three four five six seven which is the password and logged in successfully so that did actually work now again i know this isn't really bringing us anywhere but that's the next step so now that login and sign up is working first of all from login if we log in successfully we need to redirect the user to the home page we're going to say return redirect url for views.home just like we did in the signup page all right awesome so we're getting very close to being done here um i mean we have to add the notes and stuff but like we've done most of the hard stuff already now that we can log in and we can sign up we need to be able to log out we also need to make it so that you can't access the home page unless you're signed in right we want to prompt you to log in or to sign up for an account if you haven't done so already so now we need to make it so that first of all you don't see this home button if you're not logged in you can't access this home page if you're not logged in and if you're logged in it probably shouldn't say log in or sign up at the top it should probably only show you home and log out so how are we going to do that well this is where we're going to use flask login so this is makes life super easy i love the fact that this module exists we're going to start by just importing flask logins we're going to say from flask underscore login imports login user import actually login required yeah import login required and import log out user awesome so these are the functions we're going to use to log in our user we're also going to import something called current user which is going to represent or hold the current user now this is the reason why we needed to in our models file have this user mix in so that we can use this current user object here to access all of the information about the currently logged in user so anyways what we're going to do now is inside of login after we log in we're going to say login user we're just going to pass our user like that so the user that we found here that we have the correct password for this is the user we're logging in that's all we need to do this is going to log in the user last thing we'll say remember equals true now what this does is this remembers the fact that this user is logged in until the user i guess clears their browsing history or their session this is going to store in the flask session so after you restart the flask web server this will no longer be true but if the web server is running it's hard to describe when this is is not going to remember the user but essentially just think of it as unless some circumstance occurs where the user like clears their browsing history or the web server restarts flask going to remember that this user was already logged in so they don't need to log in every single time they go on the website anyways login user user remember equals true now we're going to do the same thing so just copy this line in sign up so after we successfully sign up user we're going to log them in as well because well they should be logged in after they create their account and then we'll now do the log out function or the log out route here so in logout what we want to do first of all is we want to return the redirect for the for and then we're going to just redirect uh to auth.login which is uh just going to be this right here we're doing that because after they log out usually just bring them back to the sign in page right and then all we're going to do inside of here is we're going to say log out user and we don't need to pass a user we just say log out user and it will log out the current user now lastly we're going to add a decorator to this this function here that says login underscore required now all this does is this makes sure that we cannot access this page or this route unless the user is logged in and this makes sense right we don't want to be able to log out if we're not logged in now that's not going to cause an issue but it just makes sense to add this decorator so we will so we have that for log out now and now i'm going to copy this line i'm going to go to views.pi i'm going to show you how we can do this in here so now all we need we don't need login or log out user we'll get rid of those we're going to keep login required in current user though and we're going to add a login required decorator to our home page so now you cannot get to the home page unless you log in and there you go now the last thing we need to do here when we're using flask login is we need to tell our flask in general how we actually log in a user how we find a user so we need to go to our nit.pi file and inside of here we're going to say at the very top from flask underscore login import login manager login manager is what it says it's going to help us manage all of the logging in related things so at the top here under db.net app we're going to say the following we're going to say log in underscore manager equals login manager just like that we're then going to say login underscore manager dot login view so where do we need to go if we're not logged in so essentially where should flask redirect us if the user's not logged in and there's a login required well we want to redirect to auth.login name of our template name of our function right and then we're going to say login underscore manager dot init underscore app and then pass it the app so telling the login manager which app we are using then lastly we're going to define a function here we're going to say at login manager underscore manager dot user loader and we're going to say define load underscore user is going to take an id and inside of here we're going to return the user dot query dot get int id now i'm going to describe this in a second but sorry take all this code we need to put it below when we import this model here so actually below the database after we create the database then we're going to do this now i'll go through this but i think these three lines are straightforward what this is doing is this is telling flask how we load a user now user.query.get this works very similar to filter by except by default it's going to look for the primary key so when you use get you don't have to specify like id equals id it just knows that it's going to look for the primary key and check if it's equal to whatever we pass which is the int version of whatever id is passed to this load user now you don't really need to know much more about this but we're just pretty much telling telling flask here what user we're looking for we're looking for the user model and we're going to reference them by their id and that's what this decorator here is doing it's saying you know use this function to load the user if you had more advanced loading of users and obviously you would have to change this function but hopefully that's clear again it doesn't matter too much if you understand that or not just we have to use for login manager and for for flask lock-in okay so now that we have that i think that's pretty much all we need so let's re-run this here and let's check if this is working so let's refresh uh please log in to access this page notice we're getting that popping up so to access this page that's i i don't know why it's showing me this message because i don't think we um we implement this anywhere but if i go to home it keeps saying that log out i mean it's not doing anything because login is required right if i go to sign up i can sign up go to in i can log in so let's log in tim gmail.com and let's go with my password and boom logged in now we can access the home page awesome so now if i go to login i mean it brings me there i can go back to the home page because i'm currently logged in if i log out it redirects me to the login page and i can no longer access the home page so that is how that works that's what flask login does for us it kind of manages what pages we can access and what ones we can't and stores the fact that users logged in or not so now i want to show you how we can change this nav bar so it only displays the correct icons so this current user thing that i had imported in views.pi this is what we're going to use to detect whether a user is logged in or not so this current user has a bunch of attributes if the user is logged in it will give us all the information about the user so their name their notes their email anything on the user model we can access from current user if the user is not logged in then it will tell us that this user is i believe what's known as an anonymous user and it is not currently authenticated because we've not signed in so what we're going to do is we're going to pass to our home template user equals and then current user now what this means is that we will be able to in our template reference this current user and check if it's authenticated so let's go to our home.html template and inside of here actually not home sorry let's go to base.html and inside of base.html what i'm going to do is i'm going to go to my nav bar and i'm going to do some if statements and only show some of these links if the user is signed in so i'm going to do if like this so if and then user dot is underscore authenticated like that did i spell authenticated correctly i think i did so if they're authenticated then all we're going to show is log out in home right so let's do that here we will show home first probably and then log out after so put home above then otherwise so inside of here we'll go percent percent else and then percent percent and if okay so otherwise so if they're not logged in then we'll show the login and sign up buttons if they are then we only show those so now that we have that that's all we need to do to handle the navbar we just need to make sure that whenever we render this base template which is in all the templates we pass the current user i'm going to save that i'm going to go to auth now i'm going to do the same thing for my render template so i'm going to get rid of boolean here and for login i'm now going to pass user equals current user same thing for my log out although actually no i don't need to do for logout sorry just for sign up now i'm going to pass user equals current user so now if we have access to the current user we can use it in our template and then we'll display the correct thing for the navbar so let's rerun this and let's go to our website and let's refresh so now notice that those two things went away we're not uh logged in so we only have log in and sign up but if we log in so tim gmail.com and uh what was the password okay then we get home and we get log out and now i can go to the homepage obviously or i can log out and it redirects me here so that is how you do that awesome so now that we have that what i want to do is i want to talk about adding notes and yeah and then at that point we're going to be pretty much done so let's go to our home page and we're just going to add kind of that little form or the little ui aspect to allow a user to add notes and we'll also have to display all the notes as well so let's start by allowing user to create a note so we're going to make a form so we're going to say form and then method equals post like that and then here we'll say slash form now we need to make a text area for the notes we're going to say text area we'll say name is equal to note id is equal to note and the class will be equal to form hyphen control then we will end the text area and then we'll do we will create a button so we're going to say div we're going to say align equals center just to put this button in the middle of the screen i'm going to end the div we're going to add a button i'm going to say button type equals submit class equals btn btn hyphen primary we're going to say add note and then we're going to end the button all right so now we have a form and when we press this it will send a post request to our url with the note okay so now we have the form let's write some code that can actually generate or show all of the notes so first i'm going to make an h1 tag and i'm going to say align equals center i'm going to end the h1 and then i'm going to say that this is notes and then under here i'm going to write a list group that's going to allow me to show all of the different notes so first i'm going to make ul which is like what you do for list i'm going to say class this is a bootstrap class list hyphen group list hyphen group hyphen flush uh and then we're gonna say id equals notes then we will end the ul and we're gonna do a for loop to loop through all of the notes so i'm going to say percent percent for user dot notes now remember we're always passing user right and since we're passing user what we can do is we can access all of the notes associated with the user because they have that if we go to model sub pi here they have a notes field that is actually going to store all of our notes so we're going to say for note in user.notes we're going to end the four so we don't forget and then what we'll do is we'll just display the node.data so we'll say note dot data like that and the data again is just the text associated with the note we also could display the date of the note but i'm not going to do that for right now okay so now that we have that let's just put this inside of an li tag sorry just so it shows up nicer and i will change the li tag so we have a class here so for li i am going to say class equals list hyphen group hyphen item sweet okay so now that we have that we should actually display all of the notes um i'm trying to find a word here just in a list and that should be good okay so now we'll dispel the notes then we have this form so let's go to the homepage and see how this looks so let's sign in i guess tim gmail.com and there we go and now notice we have add note method's not allowed that makes sense and then we have the note field like this now for some reason my cl oh well it would be helpful if i spelled class correctly i was like my that looks really bad anyways now we have the button that's proper but what i want to do is in between the text area and the div i'm just going to add a break line just there's a bit of space so br and then slash and now let's refresh this and notice we okay that's much better that looks a lot better so moving on let's make it so we can actually add a note now we kind of already know how to do this we're at the point where you guys you know you could probably go off on your own now let's go to uh views.pie and we're on the home page we now need to make it so that the the post method is allowed for this route so i'm going to say methods equals and then get and then post all right so now we'll check if the request dot method and we need to import requests so let's import requests like that is equal to post so if request.method equals equals post then what we need to do is get the notes we're going to say note is equal to request.form dot get note i'm going to go a bit faster because we've done this a few times now and we're going to get the note and we're just going to make sure that this note is at least length one so we're gonna say if the len of note is greater than or equal to one or sorry is less than one then we will flash uh note is too short and then i guess we'll just go with category equals air okay otherwise what we will do is we'll flash note added category equals success and then obviously we're going to have to actually add the note so how do we add the note so to add the note what we need to do is we need to say new underscore note is equal to note which means we need to import that so we're going to say from dot models import note and then we're going to say for this well the data of our note is equal to note so whatever the text is that was passed for the form and then the user id of our note is equal to current user dot id because with the current user we can access any of the fields on it like the id so that will create our note there's nothing more we need to pass this then we will say db dot session dot add new underscore note and then lastly db.session.commit and then i guess we actually don't need to add anything we just do that then we will flash node added we will return back to the home page and we will render that note so i believe that's all we need uh to actually add the note i think that should be good and then yeah you'll see it and it will show up on the page awesome now that we have that one more thing that we need to do is we need to import db so we're going to say from dot import db i knew i was missing something and let's rerun the web server so now let's see if we can create a new note so let's go and let's refresh and let's say hi add note and name flash is not defined okay we need to import that so from flask let's import flash now let's refresh continue and notice that we added now we added it twice just because the post request was sent twice but there we go so we added it on now what i want to do is show you how to delete the note so let's just go low and make sure this one works notice hello is now added and now i'll show you how to delete them so let's go to home.html and i'm going to add a button for all of our notes that allow us to delete it so underneath note.data but still inside of our li here we're going to say button type equals and then this will just be button class equals close and then on click equals we're going to call a javascript method which we'll write in one second our javascript function then we will end our button so slash button and we will add that little icon that's the x that we used previously so we're going to say span and then area oops hyphen hidden which means like just don't show this uh equals and then true and then end the spin and then we're gonna do that little fancy symbol again so ampersand times semicolon save that and now we need to write the javascript function we're going to call uh you'll see why we need to do this but this is kind of the way that we would delete something i'm trying to find the words to describe this i'm just going to do this and then you'll see kind of why we need to do it but since we're not submitting form data and instead when we press the button we want to send a request to the back end this is kind of a standard way to do this there's of course other ways to do this but we just write a little bit of javascript that will send a request to the back end for us that will delete the the note so we're going to say delete note is the name of the function we're going to write and then inside of here we're going to do two squigglies and we're going to write note dot id so the reason for this is that we need to be able to figure out which note we're deleting and of course we want to delete the note with whatever id is in this field so we need a way to figure out which note we pressed on and the way we do that is since we're in the for loop we're going to say that on click we call the delete note with note id so i feel like i'm explaining this very poorly but we will have a function in javascript called delete note that will take in a note id we are specifying that we want to pass the id of the note that we're showing in this list column or this list row and then that way when we press on the close button in this row it will send the note id associated with this note and we will delete that note from the database so let's save that for some reason it's giving me some some red squiggly lines here i think this should be good i'm just double checking to make sure i did everything successfully or correctly i think i did let's go now to our index.js now remember i showed you how to add this in the beginning part of the series in case you're or serious beginning part of the video in case you're forgetting how to do that if you go to base.html this script tag right here is referencing this index.js file which we have stored in the static folder so make sure you have this line in your base template at the very bottom and that it looks like this and that you name your file index.js unless you modify that line anyways inside of here let's write what we need so we're going to say function delete note we're going to take a note id and we're going to send a request so to send a request in vanilla javascript you use fetch and then we're going to send it to an endpoint we've not yet created called delete note and inside of here we're going to pass the methods we're going to say method equals post we want to send a post request and the body is json.stringify and we're going to send note id and then being note id now i'm just going to type this out then i will explain it don't worry we're just going to say underscore res and then we're going to make an arrow function let's say window dot location equals sorry dot href equals and then slash okay so what this is going to do is it's going to take the note id that we passed and it's going to send a post request to the delete note endpoint which we've yet to write which we'll write in a second and then after it gets a response from this delete note endpoint it's going to reload the window this is how you reload the window with the get request specifically so window.location.href equals slash just means redirect us to the home page which in turn will just redirect the page all right sorry refresh the page so that's what this is doing uh don't worry if you don't understand the javascript this is all we need to delete the the note and this is just how you send a really basic request to the backend from javascript we're not using ajax or anything like that so let's go now to views.pi we need to make another view so we're going to say at views dot and then root and we're going to call this one we do need methods actually we're going to call this one delete note now methods is going to be equal to post and it's only going to be post there's no get requests we can send here just post we're going to say define delete and then underscore note and what we're going to do is we're going to look for the note id that was sent to us now it's interesting how we have to do this because we're sending the request not as a form so the request is actually going to come in in the data parameter of our request object which you will see in a second which means we need to load it as json so i need to import json which is built into python so import json up top and we're going to say that the note is equal to json.loads and then we're going to load the request dot data then what we're going to do is we're going to say note id sorry is equal to and then this is going to be data at note so what this is going to do is it's going to take this request data which is a string this string is what we just sent from here so it's going to be note id and then node id and and what this dot what this does json.stringify is it turns this into a string so we need to now take the string from views.pi turn it into a python dictionary object so we can then access the node id which is going to come in as the field node id and then what we're going to do is find this node so we're going to say note is equal to and then note dot query dot get and then note id so again when you use get it accesses the primary key which is what we're what we have here anyways so if we found a note so if note does exist then what we will do is we'll say if note dot user underscore id equals current user dot id then db.session dot note this is how you delete an object you query it and then you just put it inside of the delete there i don't know i added a semicolon and that will delete it then you say db.session.commit and then we can just return something so i'm just going to return jsonify which i'll import in a second with an empty response now i'm going to talk about all this don't worry i know i'm going fast but at the top just import jsonify and let's discuss this so this that i just wrote here what this is doing is it is going to take in some data from a post request it's going to load it as a json object or a python dictionary we're then going to access the note id attribute which again is right here what we'll do then is we'll say note.query.gets we'll look for the note that has that id check if it exists first of all if it does exist then of course we can delete it if it doesn't we don't need to delete it and then what we'll do is we'll say well if we own this note so if the user who is signed in does actually own this note because we don't want to let users who are signed in delete other people's notes right then we will delete the note so just a little security check and then what we'll do is we'll return an empty response now we just need to do this because we do need to return something from these views we're not returning html here we're just returning an empty response that is either saying hey you know it was successful or it didn't work or whatever and in fact at the very bottom here we can just return jsonify no matter what and we're just jsonifying an empty python dictionary which essentially means turn this into a json object that we can return and well we're not returning anything but we just need to return something it's just like a requirement from flask so anyways that's what we need to do that should now delete our notes so now let me get out of this let me run the server and what's the issue here if note ah i used one equal sign this should be two equal signs okay let's rerun this so i just had one equals that needs to change to two now if we refresh uh i don't want to do that let's just do this notice that we have our x's now and if i press my x no the requested url was not found on the server interesting so looks like we must have sent the wrong url uh name data is not defined oh oops sorry guys this should be note uh first of all that should be note so that will fix one of the errors and let's see what other error we had delete note was not found on the server it should have been found on the server we have delete note here interesting okay i'm just going to try this again and see what's wrong let's refresh let's go back to slash home oh that's why we don't want to go to slash home we just want to go to slash and i think the issue is in index.js no i'm just looking around for the problem here for some reason we got redirected to slash home i don't know why that happened um anyway sorry let's let's just try this again okay so let's refresh let's try to delete a note it says it was not found on the server okay i'll be right back after i look for this all right so i fixed the error it was actually just a caching issue with my like previous version of this project before i started the tutorial uh so you guys shouldn't run into that issue there's nothing that you need to fix i just cleared my browser cache by going up here and pressing empty cache and hard reload when my console was open anyways uh now we can delete nodes so if i go test and i add it i can press the x and it deletes the note so that is actually it that's all i wanted to show you that has been this tutorial now this took us almost two and a half hours i do apologize that this was a long time but i hope you guys can appreciate the effort here the amount of time i just sat in front of the camera and talked to you and this gives you a really good start on your project this again is how you create user accounts how you actually associate information with users and i'm really hoping that now you're going to have you know some strong fundamentals in flask and have a nice template project and you can get you guys can go out and build your own interesting website so anyways that is it i'm going to leave it here if you guys enjoyed please do make sure to leave a like subscribe to the channel and of course i will see you in another youtube video [Music]
Info
Channel: Tech With Tim
Views: 480,947
Rating: 4.9624567 out of 5
Keywords: tech with tim, build a website with python, how to make a website with python, how to use flask to build a website, beginner python tutorial web development, how to create website user logins with python, website authentication with python, tech with tim python tutorial, how to use flask and python, how to build a website with flask, flask sqlalchemy tutorial, handling post requests python, adding user notes python, sign up page html python, flask, python website, website python
Id: dam0GPOAvVI
Channel Id: undefined
Length: 136min 39sec (8199 seconds)
Published: Mon Feb 01 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.