# Python Flask Tutorial: Full-Featured Web App Part 6 - User Authentication

## Метаданные

- **Канал:** Corey Schafer
- **YouTube:** https://www.youtube.com/watch?v=CSHx6eCkmv0
- **Дата:** 04.05.2018
- **Длительность:** 47:15
- **Просмотры:** 423,416

## Описание

In this Python Flask Tutorial, we will be learning how to add users to our database. We will then create an authentication system so that users can log in and log out of our application. We will be using the flask-bcrypt and flask-login extensions to help us with this. Let's get started...

The code for this series can be found at:
https://github.com/CoreyMSchafer/code_snippets/tree/master/Python/Flask_Blog


✅ Support My Channel Through Patreon:
https://www.patreon.com/coreyms

✅ Become a Channel Member:
https://www.youtube.com/channel/UCCezIgC97PvUuR4_gbFUs5g/join

✅ One-Time Contribution Through PayPal:
https://goo.gl/649HFY

✅ Cryptocurrency Donations:
Bitcoin Wallet - 3MPH8oY2EAgbLVy7RBMinwcBntggi7qeG3
Ethereum Wallet - 0x151649418616068fB46C3598083817101d3bCD33
Litecoin Wallet - MPvEBY5fxGkmPQgocfJbxP6EmTo5UUXMot

✅ Corey's Public Amazon Wishlist
http://a.co/inIyro1

✅ Equipment I Use and Books I Recommend:
https://www.amazon.com/shop/coreyschafer

▶️ You Can Find Me On:
My Website - http://coreyms.com/
My Second Channel - https://www.youtube.com/c/coreymschafer
Facebook - https://www.facebook.com/CoreyMSchafer
Twitter - https://twitter.com/CoreyMSchafer
Instagram - https://www.instagram.com/coreymschafer/

#Python #Flask

## Содержание

### [0:00](https://www.youtube.com/watch?v=CSHx6eCkmv0) <Untitled Chapter 1>

hey there how's it going everybody in this video we'll be learning how to use our application to add users to our database and also how to authenticate users so that they can log in log out and also soon be able to create posts and things like that so let's go ahead and get started so in a previous video we created our database and saw how we could manually create some users and posts but now let's add that same logic to our application to create these users through the registration form now before we create our users we're going to need

### [0:29](https://www.youtube.com/watch?v=CSHx6eCkmv0&t=29s) Hash Our Passwords

a way to hash our passwords so in the previous video we were using plain text passwords for our examples but you never want to do this with your actual website because if anyone was to ever get access to your database then they would have the logins for all of your users and that's definitely not a good thing so there are several different hashing algorithms but one good one that we can

### [0:50](https://www.youtube.com/watch?v=CSHx6eCkmv0&t=50s) Bcrypt

use is called bcrypt and there's an extension for flask that makes this easy to use and that is

### [0:55](https://www.youtube.com/watch?v=CSHx6eCkmv0&t=55s) Flask Bcrypt

called flask bcrypt so let's pull up our command line and install this with pip so I have my virtual environment activated and I'm here in my project directory and I'm going to install this just by saying pip install and this is flask - be crypt so let's install that and once that is installed I'm going to clear my screen here and now let's open up python from our command line and see how this works so i'm going to import the bcrypt class from that flask extension so i'll say from flask underscore bcrypt import this bcrypt class and now we'll create an instance of that class will say bcrypt is equal to this class and put in those parentheses there and now let's hash a password so we can say be crypt and we can use the generate password hash method and then pass in a password and I'll just of testing for now and we can see that this created a password hash in this be here at the beginning means that this is in bytes now on the extensions documentation page they say if you want a string then you can simply decode this to utf-8 so if I rerun that password hash and do a decode of utf-8 then now we can see that we a similar hash but there is no longer to be at the beginning there so that's just a regular string okay so one thing to notice here is that each time I run this I get a different hash even when using the same password so if I do this again then this hash is different than the one before and if I do it again then it's completely different than the one before so this means that if someone was to steal this from your database then they wouldn't even be able to use a hash table to crack these passwords so if it's a different hash every time then how can we verify if the user enters the correct password if we just hash they're entered password and can compare it to what we have stored in the database then those will most likely be different so we need to use another method called check password hash in order to check if those passwords are equal so I'm going to save this hash password as a variable so I'll rerun this again and I'll just say that this is our hashed password and remember the password that we used there was the string of testing so now let me clear this out so we have some more room here and now let's check a few passwords against this hashed password so if I say be dot check password hash then first we want to pass in the hashed password so I'll pass in that hashed password and now let's compare this against a password of password so this should return false since our hash password was originally testing so we can see that we did get a false value there but if I pass in testing and check that then that gives us a true so that is how we are going to hash and verify passwords so let's add this to our

### [3:54](https://www.youtube.com/watch?v=CSHx6eCkmv0&t=234s) Application Initialization

application initialization so I will exit out of this and clear my terminal and now let's open up our project and I am within my package and knit dot pie file here where we are initializing our application and now to initialize this it's going to be pretty similar to SQL alchemy here so we'll just say from flask bcrypt import that bcrypt class and then down here at the bottom we will say be crypt is equal to decrypt and we want to pass in that app to that bcrypt class to initialize that okay so now let's open up our routes and see what our current registration logic is so if I go to the routes and go to our registration route here and I'm going to make this text a little larger so we can see better here okay so right now we are checking if this form is valid on submit and if it is then we flash a message that an account has been created for the user but we're currently but we aren't currently creating that account so let's do that so if the form is valid on submit then first let's hash the password that they entered so that it's ready for us to save it to the bait database so first we need to import bcrypt and the DB variables and remember if we're importing from our package then it's going to import it from that Annette PI file but we can just simply write that as if we're importing from the package itself so we're already importing this app from that package so now we need to also import the DB and our bcrypt okay so now let's go back down to our registration route and inside of our validate on submit conditional here and this will basically be the same thing that we just saw a second ago in the command line so I will say hashed password is equal to be crypt dot generate hashed well actually that is generate password hash and then we want to pass in the password that we want to hash and this is going to be whatever they insert into the password field so that is form dot password dot data and now remember if we want this to be a string instead of bytes then we can do a dot decode of utf-8 and I'm going to close the sidebar here so that we can see more of this line okay so now that we have a hashed password now we can create a new instance of a user and we saw how to do this in a previous video so we can do this just by going to the next line and creating a new user so I'll say user is equal to user and now we have to pass in all of the fields so we want the username of this user to be equal to the information that they passed into the username of fields audio username data and now we want to set the email of this user equal to form email data and then we can set the password for this user and that password is going to be equal to our hashed password we don't want to pass in the data that they passed to the form because that will be the plain text password we want the hashed version of that okay so once we have that user created then we can go to the next line here and add this user to the changes that we want to make to our database so we can do this by saying DB session dot add and then adding that user and now we also want to commit those changes it's only one change so we can say DB session dot commit okay so that will add the user to the database now let's flash them a message telling them that their account has been created and that they can now log in so instead of the message that we currently have here I am instead going to pass in a message it just says your account has been created you are now able to log in and again we'll keep that success category there because that is the bootstrap class and now instead of returning them to the home route let's return them to the login route so that they can login with that newly created account okay so now let's see if this part worked so let's start up our website so I'll bring up our terminal here our command line and I'll run this application just like we've seen before with Python run dot pi so our server is running we didn't get any airs so I will open this up ok and the website looks good so now if I go to the registration page so if I click sign up with nothing there we can see that the validation is still working so that's good and now let me

### [8:45](https://www.youtube.com/watch?v=CSHx6eCkmv0&t=525s) Create a Dummy User

just create a dummy user here so Cory M s and Cory M Schaefer at gmail. com and the password I'll just put in as testing so let's sign up okay so with valid form information we can see that we now got redirected to the login page was not with our flashed message telling us that we can now login now our logins still aren't working but it looks like our user was added to the database but let's make sure of that though so I'm going to bring up my command line and stop our site from running so I will kill that with control C now I'm going to clear this and I'll start up Python and import our database user model so I will say from flask blog import DB and we also want to import our user model so we'll say from flask blog dot models import user and now let's grab the first user out of this table so I'll say user is equal to user query dot first and we saw how to do this in a previous video so if you haven't watched our database video then you might want to watch that to understand what these queries are doing okay so now let's print out that user and we can see that we got a user with the username of core DMS the email of khorium Schaefer at gmail. com and our default JPEG profile picture so now let's look at the password for this user so if I say user dot password then we can see that we do get a hashed version of a password and that's exactly what we wanted okay so that's good but if we go back to our application then there's actually something wrong with how we have this right now that might not be obvious right off the bat so currently our registration form will validate against things like bad emails and empty fields but there's nothing stopping a user from trying to sign up with a username or email that already exists in our database now we have a restriction set on our database models that say that those have to be unique but that won't be caught or throw an error until we try to add that new user to the database so let's see what this looks like if we were to try to add another user or email that currently already exists so let's start up the website again so I will go back here and close out of the Python interpreter and rerun our application and now let's go back to our application and go to the registration route and now I'm just going to try to sign up with these same credentials that I used before so that was for EMS and Cory M Schaefer at gmail. com with password here and sign up and you can see that we get this ugly error screen where it says that we had an SQL alchemy integrity air and that the unique constraint has failed and it also prints out the stack trace here of all the code that led up to this air now this is the first time that we've seen an error screen like this is what happens when flask throws an error and you're running in debug mode this information can be extremely useful for debugging problems in your application but this is also why you don't want to be why you want to be absolutely sure that you're never running in debug mode when you deploy your website publicly because this is just too much information to expose to other people you can actually come to the bottom of the stack trace and run Python code to dig further into the problem and you need the debugger pin from your console to do this but it's still risky having that capability so for example if I wanted to debug this line here where we did the DB session dot commit then I could just click on that line or click on the option over here to the right where it says to run code here so if I click on that then it'll ask for the debug or pin and if I pull up our terminal and scroll up here a bit when we first started our server we can see that it has a debug or pin here so I'll copy that and paste that into our debugger on the site and now we can actually run Python code here within the browser to see the context of what the variables were at this point in the application so if I was to print out user and we can see what our user variable was at that point so user dot email so we can see that we can get information back so again that can be useful to debug certain problems but it's also why you don't want to be in debug mode when you're in production okay so now we need to catch the failure that we saw here before we get to this ugly air screen now you might think that it's best to go into our register route here and add in some database checks after

### [13:31](https://www.youtube.com/watch?v=CSHx6eCkmv0&t=811s) Database Checks

our form is validated to see if the username or email already exists in our database and that would be one way to do it but I think that the best way to do this would be to add our own custom validation for the register form that way it gets checked when we actually try to validate the form and we'll return the visual feedback of the error messages like we've seen before so how do we do this now I got this from the WT form documentation so if we open up our forms file so I open up my side bar here and open up our forms module to do this we want to come inside of our registration form here and go down and

### [14:12](https://www.youtube.com/watch?v=CSHx6eCkmv0&t=852s) Create a Custom Validation

now we can create a custom validation simply by creating a function within this form so I'll type this out and we can go over it so this is going to say be a function of validate field and take self and field as arguments there then we'll say if true raised validation error and we're also going to want a error validation message so validation message okay so what I just created here is basically a template for our validation methods so we're going they're going to be in this format so validate and then we're going to put the field name here that we want to validate and then also pass in at the field name here as an argument and then we're going to have some kind of conditional so this just says if true for now but we'll add in some type of conditional and if it meets that condition then we can raise a validation error with a validation message and I think this will be more clear once we customize this to our needs so let's do that now so we want to validate the user name field so we can change this field name to be user name and we also changed that argument to use your name there and the condition that we want to check is whether or not the user already exists in the database so first we need to imp the user model from our models so from the top here I will say from flask blog dot models import user and now go back to our conditional and now we can query whether the username being submitted to the form is already in our database by saying of above the conditional here will say user is equal to user dot query dot filter by and we want to filter by if this username is already in the database we'll say username is equal to username dot data now this is what's coming from the form that's what this argument is here and then we'll just get the first value back from the database so if there is a value then we'll get the first one there if there isn't a user then that's just going to return none and now we can change our conditional to something that we want to throw a validation error so if this user exists already then we want to throw the validation error so I'll get rid of these empty spaces here so we'll just say if user whoops if user then we want to raise the validation error so basically if user is none then it won't hit this conditional but if user is anything other than none then it will throw this validation error now the validation message is what gets sent back to the form so we want to be more specific so that the user knows what actually went wrong so we want to say that username is taken please choose a different one and lower case that see there looks a little weird okay so that should be good for our username validation Oh actually there is one more thing we haven't actually imported this validation error yet so that needs to be done as well and that is part of the WT forms validator so we can just add that to the import there so from WT forms dot validators add that validation error there onto the import okay so that should give us a validation error if the user name is already taken now we want the email to be unique too so let's make

### [17:44](https://www.youtube.com/watch?v=CSHx6eCkmv0&t=1064s) Custom Validator for the Email

another custom validator for the email and we can simply copy and paste this one since it will be so similar and I will paste this in right below here and now we need to change out the field names here so we can say that we want this to be validate email and also change the argument that we're passing in there so the email parameter is what we want and now for this we want to make sure that the email doesn't exist in our database so instead of username equal equaling user name data we want this to be email equals email dot data and so the conditional will be the same so if a user exists with that email then we want

### [18:29](https://www.youtube.com/watch?v=CSHx6eCkmv0&t=1109s) Validation Error

to throw a validation error and our message will just say that email is taken please choose a different one so we'll save that okay and simply by adding those custom validators that should solve our problem and catch that before we see that ugly error that we saw before so let's go back and reload our page so okay it looks like our website is still running so that's good so I'll go back to our register form so we're still on that ugly page there and now let me try to fill out our form with a username and email that is already in the system so we will fill this out and sign up and we can see that we got validation errors for both of those this one says that the username is currently taken please choose a different one this says that the email was taken and two please choose a different one so those are working and we were able to query our database and tell the user that this username or email was already taken and that they'll need to choose something different okay so now we have a pretty good registration system now we need to create a login system so that our users that have created accounts can log in and log out now to do this we're going to be using another flask extension and this extension is called flask login and

### [19:41](https://www.youtube.com/watch?v=CSHx6eCkmv0&t=1181s) Flask Login

it makes it really easy to manage user sessions so first let's install that by using pip so I'm going to open our command line here and I'm going to shut down server by hitting ctrl C and clearing this out and we can install this just by saying pip install flask

### [19:58](https://www.youtube.com/watch?v=CSHx6eCkmv0&t=1198s) Install Flask Login

login and once we have that installed I'll clear the screen here and now let's add this to our initialization of our application like we've done with our other extensions so I'll open up our code here and go to our an it dot PI file within our package and just like our other extensions we can import this and then initialize it so the class that we want to import from this extension will be so from flask login we want to import the class login manager and now we can create an instance of that so I'll save that there and down below our other extensions I will say login manager is equal to login manager and I'll pass in the app into that class ok so now we're ready to use this login manager in our application so the way that this works is that we add some functionality to our database models and then it will handle all of the sessions in the background for us so let's open up our database model so I'll open up this model stop py file here and first of all we need to import our login manager from our package and that can't comes from the same place as our DB instance so we can just add that to our import so I will add the login manager to our imports there from our flash blog package and now we need to create a function with a decorator called user loader and this is for reloading the user from the user ID stored in this session and I simply grab this from their documentation on the extensions website so it's not like I've memorized this it's just one thing that you need to put in place for the extension to work because the extension has to know how to find one of your users by ID so first let's create this decorated function so we can create a function called load user that takes a user ID as an argument so I'll do that now so load user that takes a user ID as our argument and then we can return the user for that ID and if you remember from a couple of video videos ago we can do this with the query dot get method so I'll say return user dot query dot get and we want to get the user with that ID and let's cast that to an integer just to be sure so we will pass in this user ID here and save that and now let's decorate this function so that the extension knows that this is the function to get a user by an ID and we have to use this naming convention so we will say so we'll put the @ sign to specify a decorator this is going to be login manager dot user underscore loader okay so we've almost got this extension set up but there's one more thing that we have to do so the extension will expect your user model to have certain attributes and methods it's going to expect for to be exact one is called is authenticated which will return true if they've provided valid credentials another is called is active anonymous and the last one is a method called get ID now we could add all of these ourself but this is so common that the extension provides us with a simple class that we can inherit from that we'll add all of these required attributes and methods for us so we can simply import this class from flask login and this class is called user mixin so I'll say from flask underscore login import user mix in and spell that correctly and save that and then in our user model we can simply import from this user mix in a class so I will just pass that in as a class that we inherit from now be sure that you're still inheriting from both DB model and user mixin you don't want to overwrite the DB model okay so that should be all we need to do with our extension in order for it to manage our sessions for us so now let's modify the login route so

### [24:06](https://www.youtube.com/watch?v=CSHx6eCkmv0&t=1446s) Modify the Login Route

that we can see how this works so let's pull up our routes again and go to our login route so before we were simply checking a hard-coded username and password here but now we're going to be actually checking our database if the username and password is valid so I'm going to delete what we have within our form validate on submit conditional here and I'm only going to leave this flash login unsuccessful part so I'll get rid of the current conditionals that we have and now let's put in our logic

### [24:44](https://www.youtube.com/watch?v=CSHx6eCkmv0&t=1484s) Logging in a User

for logging in a user so first of all they'll be logging in with their email so let's query our database to make sure that the user exists so I can say user is equal to user dot query dot filter by spell that right and we want to check if the their email is equal to form email dot data so the data that the user entered into the email form we want to filter if there are any emails in our database with that same email address and if so we just want to get the first user back with that email and if there isn't one then it will just return none and now I'm going to create a conditional that simultaneously checks that the user exists and that their password verifies with what they have in the database so I will say if user which will make sure that the user that we just filter by exists and bcrypt dot check password hash and now we want to compare their database password with the password that they entered into the form so first we pass in the hash password to this check password hash method so we can just pass in user dot password and that'll be what comes from the database since this is the database query here and the second value is the password that they entered into the form so form dot password dot data and save that now we also need the colon here at the end of our conditional so if the user exists and the password that they entered is valid with what's in the database then we want to log that user in so to log them in using our flask login extension we need to import the

### [26:34](https://www.youtube.com/watch?v=CSHx6eCkmv0&t=1594s) Import the Login User

login user function so I'll go up here to the top and we can simply say from flask underscore login import we want to import this login user function so let's copy this go back down to our conditional and now we'll simply use this function to log the user in so we can paste this in here and what we want to login this user and also remember that we have a remember me form and this login user function takes a remember argument as well so we can just say remember is equal to form dot remember dot data and that's just going to be a true/false value if they check it then that'll be true if it's unchecked it'll be false okay so that will login the user and after they're logged in let's now redirect them to the home page so we'll just say return redirect which we've seen before URL for and we want the URL for the home page okay and if they submitted the form and it doesn't meet our conditional here of being a valid email or password then let's just keep this flashed message here from before that says that the login is unsuccessful and the check the username and password and actually just realize that or not logging in by username or logging in by email so that should be check email and password so if we don't hit this conditional here then we just want to flash this message so we'll put in and else and then indent that flash message into the else block there so if it wasn't a successful login then they'll never hit this return statement here and they'll just end up down here at the bottom where we're simply returning the login page okay so let's try this out so let's bring up the site in the browser and I'll try to log in with the user that we created just a bit ago so if we check our site our server is not running so I will run that and then pull up the site in the browser and now let's go to the login page and first let me give it some bad credentials so I'll just say C at demo dot-com and pass in a random password so we can see that if I log in with a bad email or password then we can see that we just get kicked back to the login page with our flashed message that says login unsuccessful please check email and password okay so now let me login with the password that I chose with the username and before so I'll do kori M Schaefer at gmail. com and that password of testing so let's login so we can see that when I put in the email and password that's actually in the database then I get redirected to the home page that seemed to have worked ok so that's good so we're actually logging in users who exist in our database now there's only a couple of other things that we need to set up here and we'll be finished up with this part so one thing that's a little strange here is that we're logged in but we can still see our login and register routes in our navigation bar so if we click on one of those routes that we can see that we can get back to the login page even though we're already logged in so really if the user is already logged in and they try to go to the login or register page then we should probably just redirect them back to the home page because they don't need to be on those pages if they're already logged in to their account so in order to tell if the user is currently logged in then we can use the current user variable from the flask login extension so let's go back to our routes and import that so I will open up our routes go up to the top of our import here and where we're importing from this flask login let's also import current underscore user and now at the top of both of our login and register routes so I'll do the register route first at the very top here I will just say if the current user is authenticated then we want to return a redirect for the home page so I will do a redirect URL for and we will send them back to the home page and I will just copy this and paste this into the top of the login route as well so now let's see what happens when we try to go to the login or register page if we're already logged in so our web server still so now if I go to the home page and then try to go back to the login page then we can see we just get redirected to this home page if I click on the register page then again we just get redirected back to the home page so that's good that conditional and that redirect that we put in there is working now it's a little strange that we even see those links in our navigation if we're logged in most websites will replace those with a logout link if you're logged in so let's create a logout route to logout our user and then we'll display in our navigation when the user is logged in a

### [31:42](https://www.youtube.com/watch?v=CSHx6eCkmv0&t=1902s) Logout Route

logout route so to do this I will go back to our routes and go to the bottom here and now we'll create a logout route

### [31:48](https://www.youtube.com/watch?v=CSHx6eCkmv0&t=1908s) Create a Logout Route

that's going to be pretty short so I'm gonna just grab another route as a starting point here and get rid of these methods we don't want posts to this route and I will call this route logout and just like we use the login user function to log the user in we're going to need to use the logout user function to log the user out so first let's import that so at the very top here where we imported login user let's also import logout user and go

### [32:17](https://www.youtube.com/watch?v=CSHx6eCkmv0&t=1937s) Logout User

back down to our logout route and now within this route we can simply just log the user out and this doesn't take any arguments because it already knows what user is logged in so we can just say log out underscore user and run that function and once the user is logged out let's redirect them back to the home page so I will just grab the redirect link for the home page here and paste that in below our logout user ok and we also want to actually see this logout link in the navigation if the user is logged in so in this case we'll have to change our layout template where the navigation is created so I will open up our templates folder here and open up our layout template where those navigation links are which are right here are the login and register routes so right where we're creating these two anchor tags for our login and register routes I'm going to put in a Jinja to conditional and use that same current user dot is authenticated check that we used before so I will open up codeblocks here with some curly braces and percent signs and then we can say if current underscore user dot is authenticated then that means that the user is logged in and we want to add the logout route and we'll do that in just a second but for now I'm going to put in our else block and in the else block if they are not authenticated then we want to show the login and register routes so I will end it those into that code block and now we need to close out this if statement so curly braces and percent signs and end if okay so now let's copy one of these links here and paste this into the is authenticated section and this is where we want to display the logout route so I will change the URL for from login to log out and change the text okay so now let's save this and let's test all of this out so if we open up the terminal then we had an error for a second there whenever I saved so let's rerun our server make sure we're not getting any errors okay so our server is running if I pull up our page here then I'm already logged in and whenever I reloaded the page we can see that now we get this logout link so let me click on that logout link and as soon as I did we can see that these change to log in and register so that seems to be logging me in and logging me out let's just make sure that login functionality still works as well so I will type in the credentials of the user I created yep and we can see that now the logout link is displayed in the top right okay so the last thing that we're going to be learning in this video is how to put a

### [35:11](https://www.youtube.com/watch?v=CSHx6eCkmv0&t=2111s) A Restriction on Certain Routes

restriction on certain routes so that you can only go to those routes if you are logged in so you'll see this on certain sites all the time so say that I click on a link to edit my Twitter profile or something like that if I'm not logged in then it will take me to the login page and say hey you have to log in first before you can view this page so let's do something like this on our site so let's create a route for the users account that they can access after they've logged in so first we have to create this route so I will open our project back up and open up our routes that py file and go down to add another route here and now I'll

### [35:52](https://www.youtube.com/watch?v=CSHx6eCkmv0&t=2152s) Create an Account Route

create an account route so I'll copy this section here and paste this in and instead of log out we want this to be account be sure that you change the function name as well and we're also going to need a template for this route so we'll create a template called account HTML and we'll create that a template right now but first let's go ahead and return the template for our route that we're about to create so I'm just going to copy where we are returning a template up here and then paste this in and modify it so we want to return an account dot HTML template that we're going to create in just a second and the title of that page will be account ok and now let's create that template so within our templates directory I will create a new file and I will call this account dot HTML now I want a starting point for this template so I'm just going to open up our about template and copy this code here where we're extending from our layout and opening our block content section and I'll paste that into our account template but within our content section of our account template we'll make this super simple for now and just display the current users username so in this h1 tag here instead of saying about page I I'm going to use these double curly braces and print out the current user dot user name and now let's add a link to this route within our navigation if the user is logged in and our navigation is located in our layout template we just saw this so this is going to be visible if the user is logged in so right above our logout link we will copy that and we will paste in this account link so instead of logged out I'll say account and the URL here is going to be the URL for account so I'll save that so now if we check our servers still running we need to reach start that so I would do that now so restart our server and now if we go back to our page we can see that now we have this account link here in our navigation and if we click on this account link then we can see that it displays the current logged in users username but if we go back and log out and then try to go to this account page then we can see that we don't get anything on this screen and because it doesn't have a current user and doesn't know what user name to display so we want to put a check in place that makes a user login before they can access this account page so to do that this is extremely easy to do we

### [38:35](https://www.youtube.com/watch?v=CSHx6eCkmv0&t=2315s) Log-in Required Decorator

can use the log-in required decorator from the flask login extension so if we go back to our routes so I open up our routes file let's go up here to our imports and from our flask login extension we want to add another import here and this is going to be login underscore required okay and now I'm going to copy this login required here and now we can simply add this decorator to our account route so if I go down here at the bottom then I'm gonna simply add another decorator here and that decorator is going to be this login required that we just imported so now our extension knows that we need to login to access that route but we also need to tell the extension where our login route is located so to do this we need to go back to our an it dot PI file where we first initialize this application and right under where we created our instance of the login manager we can set the login round by saying login manager dot login view and set that equal to our login view and this will just be login and the view that we pass in here is the function name of our route so it's the same thing that we would pass in to the URL for function okay so now let's try this again in our browser so I have saved all of these files that we've changed so I'll pull up our terminal and our web server is still running so that's good pull up our site and go back to our home page so now I'm not currently logged in so we can't see the account link up here but I can still type that in manually and go to that route and if I type that in then we can see that it redirects us to our logout or login route and it says please log in to access this page so now if I was to log in with the account I've been using and then submit that then it sends us back to the home page and now if I try to access that account page again then we can see that we do access that account route and it displays the current users username okay so there are just two more things that I'd like to do to clean this up a bit so first of all the flashed message telling us to log in it was pretty ugly you may have noticed that in our video so far we've been using the flash categories to add a class to those Flash alerts now to do this within the log in message then we can go back to our an it file here and then we can just add another line here so I'm going to copy what we have here and this is going to be login manager dot login underscore message underscore category and now we're going to set that equal to the category that we want that to be which in our case is what we're using for the bootstrap classes so I'm just going to set this equal to info for the info class which in bootstrap is just this nicely colored blue information alert okay now the last thing that I want to do to improve this is when we tried to access the account page and we were logged out it directed us to the login which is good but after we logged in it first redirected us back to the home page and we had to access the account page from there so it would be nice if it would just redirect us back to the page that we were trying to access before it told us that we had to login and this is easy to do as well now I don't know if you notice this but when we tried to access the account page and it directed us to the login first it added a query parameter to the you our L of the page that we are trying to access so let me show what this looked like so our server is still running so that's good so let me log out and then try to access this account page so first of all we can see that our flashed message looks better now with that info style but also if we look here in the URL then we have a query parameter here called next and it is equal to the route that we were trying to log into before we got redirected so in our login route let's access that query parameter and if it exists then we will direct the user there after they login so I'm going to open up our routes here and let's see open up our routes top py file and go to our login route and actually first thing we're going to be accessing query parameters and we will need to import the request object from flask so first let's go to the top and import that and this is going to be from flask so we've already got some imports from flask here so I'm just going to add on to this and I will import this request object here and then go back down to our login route so now we want to get this after the user logs in so this login user line here is where we logged in at the user so then we can get the next parameter from the URL if it exists by saying something like next page is equal to request dot args dot get and we want to get that next parameter now args is a dictionary but you don't want to access next using the square brackets and key name because that would throw an error if the key doesn't exist and the next parameter is going to be optional so if we use the get method then it will simply return none if the next key doesn't exist so be sure that you are using the get method and not the square brackets with the key like you might be used to so now if that next parameter exists the next page will be equal to that route but if it doesn't exist the next page is going to be none so now and the return statement we can do something like this so I will say return redirect and I'll do a redirect to that next page route if next page which basically means if it is not none and then we can put in and else here and say else redirect for the URL for home now some of you might not be familiar with this and Python but this is called a

### [44:58](https://www.youtube.com/watch?v=CSHx6eCkmv0&t=2698s) Ternary Conditional

ternary conditional basically we're just saying redirect to the next page if next page exists but if it is none or false then just return the redirect to this home page okay so that should do it for our changes so now let's be sure that we save all of these changes and then pull up our browser so first I'll check my terminal and we have to restart our web server here and pull up our browser okay so now we are currently logged out so if we try to access our account page then it should redirect us to the login page which it did and now if we log in with the account that I created before then we can see that when we login it redirected us to the account page so that's good that's what we wanted now we also probably want to make sure that it still directs us to the home page if the next parameter doesn't exist in the URL so let's log out and simply go to the login page and since we went there directly this next parameter doesn't exist in the URL because we didn't try to access a page that required a login so now let's log in again and we can see that logs us in and directs us to the home page so all of that seems to be working well okay so I think that is going to do it for this video I hope that now you have a good idea for how you can implement an authorization system like this on your website and in the next video we'll update the user account page and make it so that users can update their information and also add an image for their profile picture but if anyone has any questions about what we covered in this video then feel free to ask in the comment section below I'll do my best to answer those and if you enjoy these tutorials and would like to support them then there are several ways you can do that these ways to simply like the video and give it a thumbs up and also it's a huge help to share these videos with anyone who you think would find them useful and if you have the means you can contribute through patreon and there's a link to that page in the description section below be sure to subscribe for future videos and thank you all for watching

---
*Источник: https://ekstraktznaniy.ru/video/12328*