Django Authentication & User Management - Full Tutorial

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
[Music] in this django tutorial i'll show you how to set up authentication for a django website specifically how to create new user accounts sign in to those user accounts and then sign out i'll also talk to you about user permissions and groups so how to assign specific permissions to users and restrict parts of our websites to those users for example in the website that we're going to build out here we're going to have two groups of users a default user and a mod user the default user will have the ability to post and to delete posts that they've created themselves and then the mod user will have the ability to delete anyone's posts because they're moderating the website as well as to ban users and if a user becomes banned then they will no longer have the ability to post but they'll still be able to view specific posts this will give you a really in-depth and kind of thorough understanding of the django permission system and grouping and allow you to do a lot of advanced stuff on your website and manage different users lastly i will also show you how we build out a really cool dashboard where we can view all of our different users see what groups they are in change the groups of users really simply from this dashboard as well as view some statistics like the new users per day the number of posts per user what type of users we have so default users mod users and view it all from one page now this dashboard that i have in front of me is going to be built using something called retool now we'll slowly build this out throughout the video but i do need to mention that retool is the sponsor of this video they are free to use you do not have to pay for this and it just allows us to really easily visualize our different data and for people that aren't programmers to come in here and actually say make a modification to our database and affect our application without having to go into the django shell you know type in lines of code and we can also do stuff like add charts and add graphs and a bunch of other customizations that we can't really do from a regular django admin page so yes some of this stuff is going to be redundant with django admin but again if you weren't a programmer this is going to be a much more preferred way to go in and view the database change different aspects of the database like which users are in which groups and then create some different charts and statistics and really anything you want anyways let me give you a quick demo of what we're going to build out here i apologize for the long intro but it is necessary to talk about this so here you can see that we have a simple website where users are able to sign in right now i'm signed in as joey and i can do something like create a post so let's just say tutorial i am demoing the app exclamation point let's make a post okay post has been created now let's go and log out here and let's sign in as the user tech with tim which is a super user and notice here that this user has the ability to delete anyone's posts even posts that they have not made themselves and to ban users now of course i can't ban myself but we just have the button there anyways so let's do something like ban joey and if i ban joey now let's log out and let's sign in as joey and now notice that if i try to make a post here so no i don't want to save that you'll see that i'm not allowed to do that now we can make a custom page for this for now i've just made it forbidden i'm still able to delete my own post because i have that permission but i no longer have the permission to make a post now if i sign in as a different user let's sign in as say susan here you will see that i have the ability to delete anyone's posts and the reason i can do that is because if i go here susan is a mod so since susan is the mod they can't ban anyone but they have the ability to delete anyone's post so i could delete joey's posts i can delete the admins post we could change that if we want to but the point is we have different users that have different permissions and that changes what they're able to do on the website obviously kind of a more advanced thing but that's what i want to show you in this video so anyways with that said that is enough for this intro i apologize that this was long now let's head over to visual studio code and start working on this project alright so i'm inside of vs code and now we can go ahead and get started so there's a few setup steps that we need to go through we're going to start by installing everything kind of setting up a boilerplate django application linking our urls and views and all of that then we're going to create a remotely hosted database using postgres i'll talk about that when we get to that step then we will build out the website we'll build out the dashboard and all the other stuff that we need to do so to get started i've created a folder here called django user management tutorial doesn't really matter where you place it but i've opened it in vs code feel free to use any editor you want but i'm just going to use vs code now i'm inside of this directory here which is going to be important for the next step but first we need to install a few modules so since we're working with the django website i'm going to pip install django i already have that so i'm not going to run that command if that doesn't work if you try pip 3. if that doesn't work for you try python hyphen m pip install if that doesn't work for you try python 3 hyphen and pip install if none of those work i will leave two videos on the screen that show you how to fix the pip command now since we're here at this step we're also going to install a few other things we're going to type pip install and then we're going to install crispy and actually i don't know if this is what it's called uh it's going to be crispy hyphen bootstrap 5 like that now this is going to allow us to have some pre-built forms that we can render on the screen using bootstrap so that's why we're installing this and then you also want to install crispy forms although this should already be installed when you install crispy bootstrap so just install this in case it will probably tell you it's already there but let's just make sure that we have that before we move on okay so now that we installed that django crispy bootstrap 5 and crispy forms we can create a django project now i will mention here that this tutorial is not meant for complete beginners in django i do have a ton of django tutorials on my channel so you can check those out if you're getting a little bit lost here with what i'm doing but i'm going to kind of skim over some of the explanations of the most basic stuff regardless though let's create a project here so i'm going to say django admin and then this is going to be start project and the name of this project can be whatever you want i'm going to call mine website now make sure you run this command in the directory where you want this folder to be created so in this case i'm running it in this directory that's where i want it to be but if you want it on your desktop then you'd make sure the path here is desktop you just have to navigate through your terminal or command prompt to get to the right path okay so let's run that now we see that we get this website directory and inside of the website folder inner folder we have all of our files here that are containing the stuff that we need as well as dot pi so now that we've done that we want to make an application for our django project so i'm going to cd into website and i'm going to type the following python and this is going to be manage.pi and then start app and i'm going to call my app main now you can call your app whatever you'd like but if you do change the name from main then you're going to have to tweak some other things so i'd recommend you just call it main for now to follow along so make sure you're inside of the website directory where the manage.pi file is and you type python manage.pi start app and then main and then you'll see it makes this main directory here and in case you're unfamiliar the app is where we're going to write most of the logic for our website and we're going to kind of link the app to the main website so the way that we do that is inside a website we go to settings.pi and there's this thing called installed apps now the app that we just made is called main so we need to throw that in here so the way we do that is we type main dot apps dot and then main config now if you're wondering where this is if you go to main and you look at apps dot pi you can see we're referencing this main config class right here so that's what we're adding in here main.apps.mainconfig of course if you change the name of your app maybe it was auth or something then you need to change this and it would be auth.apps.auth.config okay and if you want to check then again you can go to apps.pi and you'll see exactly what the name is okay so now that we have that installed apps we're also going to add a few other installed apps specifically the crispy forms and crispy bootstrap 5 that we had before so we'll start with crispy underscore forms because we're going to want to use that later and then we will add crispy underscore boot strap 5 like that so that it styles our forms with bootstrap and they look nicer than the default forms okay now that we have that inside of settings.pi that's all we need for right now we've linked the main app to the website so let's just run our server and make sure everything's working so i'm going to type python manage.pi run server and when i do that i should see that we're getting this running on our localhost port 8000 so i'm going to control click on that to open it up and let's go to our browser here let me bring this over and you can see this install works successfully congratulations and you're seeing this page because debug equals true okay that's fine and we have not configured any urls so next what we're going to do is configure some urls so let me close this server here although i could have kept it running because when you keep it running it will just update when you change stuff but that's fine for now okay so we have some urls inside of urls.pi and actually before i do this let's make a new file here in our main app called urls.pi so what we need to do essentially is link the urls from this main app to our actual website so that we can access the different views from our main app so i guess we can really start wherever we want let's just start here we're going to import something called include alongside path and we're going to put a new path here and this is just going to be an empty path and this is going to go to and then this is going to be include and we're going to put main dot urls like that now what this is saying is that the prefix is going to be nothing and we want to get all of the urls from main.urls and access them with well this prefix which is nothing so that essentially means that now any urls we put inside of this file so the urls.pi file will be able to access on our website and notice we already have these admin urls which are pre-built for us which kind of give us the admin panel and admin page which we'll have a look at later for now though let's go to urls and let's actually set up the urls inside of here so what we need to write here is from django import and then this is going to be path and then from dot views import or sorry not from dot views from import from dot sorry import views now dot is referencing the current directory because this is a python package by the presence of the init.pi file and so we're able to access this views file okay so now we're going to type url patterns is equal to a list and this is where we can place all the urls for our app so for now i just want a url for the home page so i'm going to type path we're just going to make it an empty path so when you go to the default page this is what shows up and we want to display the views.home function which is a function we've yet to create okay so that's what we need for that now we want to go to the views file which is going to contain all of our different views and here we want to write the home view so we're just going to say define home we're going to take in request we don't need star args and star quarks okay and then for now we can just return a string and we can just put a p tag in here that says home and in a minute we'll write all of the templates so the html that we actually want to render from these different views so actually quick cut here i remembered that we can't actually do this i'm used to working in flask where this works this is going to cause an error for us so what we need to do is actually make a template a template is just html essentially that we're going to be rendering onto the screen so we need to do that before we can actually view anything from this root so let's go into this main app and it's very important here that you name everything what i'm about to name it sorry i keep opening and closing this but let's make a folder here and this folder needs to be named templates and it needs to be inside of the main app if you name it something else then it's not going to work so we're putting templates inside of here then we need to make another new folder and this folder needs to be the name of your app and i'm going to call this main okay and then while we're at it we're going to make one other folder and we're going to call this registration and we'll have a look at that in a second but this is going to contain all of our authentication urls or authentication templates sorry okay so we have main and we have registration we're going to go inside of main and we're going to make a template here called base.html and we're going to make another template here called home.html now django uses something called jinga which is a templating engine j-i-n-j-a i'm probably pronouncing that incorrectly what this allows us to do is write what's known as a base template and the base template can contain uh like a navigation bar and you know default stuff that we want on every single web page and then what we can do is inherit from that template in specific templates like home.html and just override parts of it like we can override the main content of the page without changing for example the nav bar so this is going to take a minute here but we're going to write the html now someone showed me a shortcut here i might not type it exactly correct but if you go here to the language if you're working in vs code this only works in vs code i believe if you have like the html extension i think that's what you need but most you will probably have this but if you change the language to just regular html apparently you can type html colon five like this yeah okay you can see and it actually generates a kind of boilerplate template for you so this is actually what we want so this is good we'll start with this for now and we want to write the rest of this base template now what i want to do is add bootstrap here so we can use bootstrap for styling of course you can style with whatever you want but it's just the easiest way for tutorials for me at least so let's go here yeah it's because this isn't running that's fine and let's just type in boot and i always spell this wrong boot strap okay come on and let's go to bootstrap here so here from the bootstrap website we can click on get started and we can just copy the cdn which is this right here so i'm going to click on copy as well as the different scripts that we need for bootstrap so i'm going to copy that i'm going to put this into my head tag so put this link right here again you can just search up bootstrap click on get started and then you know copy the the link put that in the head tag then what we need to do is copy a few scripts and we need to put those in the body so let's go back here to bootstrap okay for bootstrap it says if you decide to go with separate scripts okay include every bootstrap javascript plugin and dependency with one of our two bundles okay i think we can just copy this one right here for the bundle and this will give us everything that we need as opposed to copying the separate scripts so let's do that and just at the bottom of our body i guess in our body here we're just going to paste in this script and now we have added bootstrap to our website so now that we've done that i'll talk to you a little bit about template inheritance and how we override parts of this base template from another template so for now let's close that and what we're going to do here is create something called a block so i'm going to type percent percent like this block and i'm going to give the block a name and i'm going to call it title now what this does is it sets up a part of this html page here that can be overridden from a page that inherits this template so let me just end the block here so we're going to type n block and we can put a default value in here like my site and what this allows me to do now is go inside of this template i can rewrite this block and it will change what's inside of it with whatever i wrote in the home page you'll see when we start going through the example but for now that's what we want and then we're going to do the same thing inside of the body but first i'm going to say div i'm going to say class is equal to and i'm just going to make this a container which is a class from bootstrap and actually we'll make this container fluid and then what we want to do here is uh place the what is it the block so i'm going to percent percent block content and i'm going to do another block here and type and block and also i'll just note here that all this code will be available from the description in case you'd uh rather just copy this out or not copy this out copy it from github as opposed to typing it out and i realize i'm going to change the container back to regular container because i don't actually want this to be fluid okay so now i have two blocks a block for my title and a block for my content and what i want to do here is just place a nav bar that will let me navigate through the website so we're going to type nav let's end the nav here we want the class here these are going to be some bootstrap classes to be navbar nav bar expanded and then large like that and then nav bar this is going to be dark and then bg dark if you're unfamiliar with the syntax it's just from the bootstrap website you can kind of just copy it out we're just going to get a nicely styled nav bar here we're going to make a div this is going to be container and this time we want it to be fluid fluid makes it so it takes up the whole screen then we're going to make a div inside of here now the first div that we have is going to contain the links on like the left hand side of our page and then the next div that we have is going to contain the person that's logged in so it'll be like you know the left and right side of the navbar essentially so div here we're going to make a ul because we're going to have some different list items here and inside of ul we're going to have a class which is equal to navbar nav so we can just have navbar nav like that and then we want to have the different links on our nav bar so do li the class is going to be a nav and then item like that although that needs to be inside of a string and we should probably spell class correctly let's end our li and then inside of this we want to have a link so we're going to say a class equal to nav link we need the href to be equal to and then in this case i'll just make it slash home okay and then we'll end the link and it will say home okay so now let's copy this let's paste this and now let's just have another one for creating a post obviously we don't have these pages made yet but we'll make them later okay so clock slash create post and there we go we have now the left side of our navbar so now let me copy this div and paste it again and then we'll do a similar thing here for logging in so let's just make a button right now or a link that says login and we can deal with showing who's logged in later okay hopefully you guys are following for now though that is what we have for the base template we will add a few things to this uh but for now that's all we need okay so let's go to home and from home we essentially just want to take everything that's inside of here and we want to override the title so it says home we want to override the content so it shows like you know you're on the home page and eventually it will show all the posts that we have so the way that we do this is we type percent percent extends and then we're going to extend and make sure this is single quotes here the main slash and then base dot html template okay now that we've extended the template that's all we need to do to extend it we can use any of the blocks from the template so i can do something like block title and say home page and then i can end the block so percent percent and block like that and then let's do another blocks percent percent block content and then we will end the block and this is where we can place any html that we want to go inside of that div so if i go back to base here this is now where we can write essentially all the html and kind of inject it into this container so if i go to block content i can just do something like h1 and then let's just go home page exclamation point and then slash h1 and make sure when you save this uh it always does this it separates the block and the content you get an error if it's not on the same line so when i do this i just hit ctrl shift p and i hit save without formatting so save without formatting you can just type that in because my auto formatter like messes everything up you may not have the autoformatter you may not have to do that but i have one so i have to go ctrl shift p save that format okay apologize that we've just gone through a lot there very quickly but we created the base page we created the home page a lot of the html we need to write is done i'm going to go to views now and start rendering this page so from use we already have render so i'm now going to return render i'm going to render the request and then i'm going to render main slash home.html okay that's all we need for right now for the home page and if we go to urls we can see we're already referencing that home function so now everything should be good if i rerun the server so let's try python manage.pi run server and we should get a nav bar with some different links assuming that we've done everything correctly although it's possible we've made a mistake so let's refresh now and there we go we get a page we get home and post and these are on uh separate lines which is a bit messed up i don't want them to be on separate lines i want them to be beside each other so let me have a look at what i messed up there and i'll be right back all right so i found the error here i accidentally typed uh typed expanded instead of expand so just change this to navbar expand hyphen lg save and then if we go back here and we refresh we should see if this is large enough that they're going to be the sidechain now when the page shrinks yeah they do go on the same line but that's fine so we're all good for them okay so now that we have done that uh what we want to do is start setting up authentication right so we've created a homepage we have our views now we want to have the ability to create users log in as users and then do the different user management create posts all that type of stuff so let's go now to views and let's start creating what we need for authentication so actually i lied i forgot that for authentication we first need to set up our database so we could do all of this locally and not host a database remotely but i want to show you how we can host one using heroku completely for free you don't have to pay for this and then that's going to allow us from retool to actually connect to the database and use and modify the database without using the django application so you'll see what i mean but let's go to our browser and let's go to heroku and let's start creating the database so go to heroku you're going to need to create account if you don't already have one again it's completely free you don't have to pay for anything and then you should be able to get to this dashboard so if for some reason you can't get there then just type in https colon slash dashboard.heroku.com and then what you're going to do is type on new here and create a new application now this app is just going to host the database for us and it won't host it forever like i believe six hours of every day the database does go down but this is just for testing purposes and to show you how to connect to a remote database so let's call this something like tutorial tutorial is not available okay django tutorial is fine okay actually let's spell django correct though django tutorial how about one two three django1234 okay great let's go with that now for the region i mean you guys can select i'm gonna go united states okay and then we need to add an application to this so to do that we're gonna go to resources we're gonna go to add-ons and we're going to click on find more add-ons and it's going to bring us to a page that looks like this we are going to search for postgres which is the database that we're going to use hit enter and we should see heroku postgres so that's what we want we're going to install this and now what we need to do is select our plan in this case it's going to be hobby dev free i mean you could pay for this if you want but we're just going to use the free plan search for an app to provision so we need to select the one that we just created django tutorial1234 and then just submit the order form and what this will do is add this resource to our application okay so let's hit submit give this a second and there we go okay so it has been installed and now what i can do is click on roku postgres like this it's going to bring me to kind of the database view i guess and not found okay there we are everything is good so we have a database we have a maximum size i think of like 100 megabytes or one gigabyte or something like that again for testing purposes this will be more than enough now what we want to do here is go to settings and we want to click on database credentials now obviously you don't want to share this with anyone else but we're going to use these database credentials to connect to our database from django without having to do any major modifications inside of jenk so let me put this on the right side of my screen let's get this not in full screen mode and put this on the left now what we want to do is make it so that all of our data is not stored in this you know local database on our computer but again it's stored in heroku then we can access it from other places as well so we're going to go to settings.pi and let me just make this a little bit easier to read let's move that down and we need to add something uh let me just scroll through here and try to find this okay so where it says databases this is what we want to modify so that rather than connecting to our local sqlite database using our base directory we're going to connect to the database that is hosted on heroic so let's change this engine here first of all to be dot django.db.backends.com then this is going to be postgres like that and then ql okay because that's the type of database that we have then for the name of the database that's going to be the name that we have here from the credentials so let's copy that in the string okay then we need to pass our username password host and port so we're going to type user in all capitals and this is going to be the user that we have here so let's copy our user put that in the string okay next we need to have our password so let's go password like that and the password is going to be the password that we have here okay so let's paste that in uh continuing we need to have the port and the host so the host is going to be whatever host it says here so we're going to copy that okay and then lastly we want to have the port now this port should be the same for everyone but it's going to be five four three two and that needs to go into string as well okay so now that we've done that believe it or not that's pretty much all we need to have this connect to the um the postgres database that we have hosted remotely we don't actually really need to change anything else there may be one thing we need to install but we'll test that out in a second so what we can do now to make sure this is working is we can go to our command line and we're going to use manage.pi just to update the database here on postgres and then we can check here and see if it worked so we're going to type the following command it's going to be python manage.pi and then we're going to type migrate and what this will do is apply all of the changes in our database to now our new database which is hosted on postgres so python managed up pi migrate let me see if i can make this a little bit bigger so you guys can read this okay that's better python managed pi migrate this will take a second and then assuming this command runs fine for you that means that everything is all good and you have connected to the correct remote database now if that didn't work for you you can try installing the following library because i had to do this previously pip install and then this is cop g2 binary for some reason i had to install this previously when i was messing around with this so if that doesn't work try installing this and hopefully that should fix it for you if that doesn't work i'm not exactly sure what the problem is but this should be good okay so now that we have that let me just refresh the page over here and we should see that some data has been added to this database and notice we've gone from zero rows to 48 rows and we have a maximum of 10 000 that we can use and our database size is 8.6 megabytes so that's good that means all the tables that we need have been created successfully and now our database is hosted remotely on postgres so now that we've done that we're going to start setting up a retool application that allows us to view this database and view all the different tables then of course we'll go through all the authentication as i was talking about before so we're going to go to the retool website here so retool.com make a new account again this is completely free you don't have to pay for it or sign in if you already have one i'm going to sign into my account and notice i have a bunch of apps here so i'm going to create a new application i'm just going to make a blank app but you could make this from one of the default ones and we'll go django tutorial like that as my application name okay so i'm brought here now to retool so let me just give you a quick demo of how this works and how we connect to a database and all that kind of stuff so you understand kind of the power of this application so what we can do here is drag and drop different components directly into the app right now it's just showing me some sample data but i can you know modify this i can make it larger i can make it smaller and i can view all of the stuff related to it on the right hand side of my screen so there's stuff like event handlers pagination i can select the different columns i can select the data that i want to use and what retool allows you to do is connect to a bunch of different data sources so if i go down here you can see that i have some sources i've already connected to like a django database github history a managed database that i have but we can also add our own resources here and view multiple resources in the same place so that's what makes this really powerful is that i can connect to a ton of different data sources and then aggregate those data sources together and view them all in one place so let's start by making a new resource here in retool because we need to connect to our database and view information about our different users and tables and all that kind of stuff so just in case you don't see this you can toggle the bottom panel using these buttons or the left panel and the right panel as well but click here where it says resource you should have a default query for some reason you don't have that you can make a new query and go to where the resource is and just hit create new resource and we're going to select postgres because that's the resource we want of course there's a ton of different ones that you could connect to so let's go here and now we need to copy that information from the credentials page again into here so i won't bore you with doing that let me grab all that data then i'll be right back all right so i've added all of that data again you can find that from the credentials tab on heroku now just make sure you check connect using ssl you don't have to modify this but you need ssl otherwise this isn't going to work and actually let me have a look at this right here we are not going to check that we don't need the self-signed certificate that's fine for now though for the name of this we can call this whatever we want i'll just call this django tutorial okay as our resource all right so let me create this resource here and now what we should be able to do is actually send queries just regular sql queries to this and view that data so what i'm going to do here is just write a query that allows me to view all of the default tables that we have in our database just to get a sense of how this works and then we'll come back to this tool later on so for now i'm going to type select star from and then i want to select this from the pg underscore and then this is catalog i don't know if i spelled that correctly i think that's fine and then dot pg underscored tables and this will give you all of the tables that are in the database so let's just run this save and run and when i do that i should get a preview password authentication failed okay so let me just edit this resource because i guess the password i put in is wrong all right so i just updated the password looks like i just made a mistake there when i was typing in let's rerun this though and now you'll see that we actually get some data so let me make this a bit larger so that we can view this you can ignore this warning we don't need that oh we don't need to worry about that for right now i notice we can view all of the different tables that are by default going to be added into our uh what do you call it postgres database so we have django migrations django content type auth permission auth group auth group permissions pg type off user these are just by default in django in the database and then of course if we create our own models uh those will be added here as well anyways that is what i wanted to show you for now we also can make it so that this table shows us all of that if we want so to do that i would just click on this table here it's called table 1. i can say you know tables because we're going to view all the tables and for the data i can remove this and i can actually instead reference the value of this query now the way i reference the value of the query is i put this inside of two sets of curly braces and i type in the name which is going to be get tables.data so now it's accessing this query that we wrote here and i can just view all of the data that i'm viewing down here inside of this table so just a demo there of how easy it is to actually use retool to visualize some data okay anyways now that we have that let's leave that page open we don't need to look at it right now let's set up the authentication and then we can come back here and we can view all the users and stuff that's being created in our database okay so let's go back to vs code uh we can get out of settings for now and we can now go to actually where do we want to do this so sorry for the bit of confusion here i'm just trying to think what order i want to do this in because there's many different ways to go about doing this let's actually get it out of views my apologies let's go to urls.pi here for our website so what i need to add here is a path this is just going to be an empty path again and then this is going to be include and we're going to include django dot and then contrib dot auth dot urls now these are a bunch of pre-built urls that will actually automatically do things like login log out password reset uh there's a bunch inside of here and all you need to do to allow these to work is to write the forms for them or to write sorry the html templates for them so that's why i said we had to make this registration folder inside of templates because now what i can do is make a template called login.html i don't have to manually render this template what will happen is that the login route that's provided by django will automatically render this login page whenever i go to the slash login url hopefully this makes a tiny bit of sense but these are kind of pre-written urls or routes and they will render specific templates that have specific names now those templates need to be inside of the registration folder and they need to have whatever the corresponding name is of the url so login is one of them but you can also override like the forbidden template you can override password reset you can override a bunch of them i just want to override the login one though and i'll show you again how this works so let's go into login and what we're going to do is type extends and we're going to extend from the main slash and let's just make these single quotes to be consistent and then this is going to be based.html okay we want to extend that template we then want to override our two blocks so we're going to say percent percent block title let's end our block uh percent percent and block okay and let me just copy this and we'll do the same with content okay block content like that for the title we'll say log in and then for the content we're going to have a few more things now above the content i also need to write a another tag here and this is going to say load and we're going to load the crispy underscore form underscore tags like that and actually it's going to be crispy forms tags now this is going to allow us to get access to the following two tags uh the tags that we need are the percent percent crsf and then underscore token let me just make sure i spelt that right crsf nope cs cs and then rf token okay and then we need one more and this is going to be form and then we're going to pipe and we're going to put crispy okay let me just code out a bit of html here and then i'll explain why we need this so we're going to have a form and then we're going to end the form okay so what we're doing here for the login page is we want to display a form that's provided to us by django that's why we wanted to have crispy forms now whenever we have a forum that has an action like post because the method of this form is going to be a post form that means that we need to add the csrf token inside now this token is kind of a security feature i won't explain exactly how it works i'm not an expert on it but essentially whenever you have some type of form that has an action and it's going to be hitting an endpoint on your server you need the csrf underscore token so if you get something saying csrf token missing then add this inside of your form now you don't need to load the crispy form tags to be able to do this at least i'm pretty sure you don't but this part you do need the crispy forms tag loaded for so let me just take a quick pause here and explain what's going on so we have our form it has a method of post but if add another method like delete put whatever it'd be the same thing whenever we have that we need to place the csrf token inside of the form now this is kind of a security feature for django i won't explain it much more than that but if you ever get an error saying you're missing your csrf token it's because you need to embed it inside of every form on the page that's going to be actually interacting with the server or sending a request to it and of course this post is going to do that this form is going to do that because it's a post method then we have form crispy now what this is doing is saying there's going to be a variable here passed to this template called form now form is going to contain like the email address the password anything else that you would need to sign in in this case the form is going to have all of that and we put this little pipe here which i believe in django actually stands for filter uh and then we put crispy now what that means is we are going to use crispy forms to display this form that's essentially what's going on now in case you're unfamiliar with this whenever you want to embed a variable inside of your template you do it with two curly braces like this so that's why we're writing two curly braces writing form which is a variable and then we're kind of using this crispy i'm gonna call it a filter could be really it's probably called something else but we're gonna use this crispy filter to actually display the form okay that's pretty much all we need i will just add a few other kind of nice touches here so i'm going to add an a tag this is going to have an href equal to and this will be slash sign up and i'm going to say don't have an account question mark and we'll say create one and actually i realized that i've done this kind of wrong this needs to be a p tag and then inside of here we're going to have an a tag and we're going to create one here so that you can create a new account by clicking on that button okay that's good and then lastly we just need a button here and the button is gonna submit the form for us and allow us to log in so i'm gonna say button type is equal to submit for the class we're going to say btn btn success this just makes a green button and then we'll say log in and when you hit that button it will submit the form so i'm going to save this notice it kind of messes everything up right so i've got a change this manually to make sure these are on the same line let's save without formatting and now the login template has been created okay so pause the video if you need to complete that but going back here urls.pi since we've added these urls now you'll see when i go to the login page it will display this template automatically so let's run our server i'm not sure if it's running already it doesn't look like it is okay so python managed up high uh oops let's cd into website first cdn's website python manage dot pi run server okay and the file name directory or label is incorrect okay let me have a look here and see what's wrong okay so i'm just searching around for that problem kind of a weird error first of all go to your settings.pi and under your installed applications just drag in these two lines here or i guess type them in crispy allowed template packs and crispy template pack this just makes it so we're going to use bootstrap 5 as the default templates okay so drag those in you might not need to add those but for me at least i needed to add those and then what i'm going to do is rerun my server so python manage.pi run server and everything should be good now when you guys ran your server it may have worked for you um i had some other problem that i've fixed it's not really relevant to you it's just in my environment i was running a virtual environment that didn't have bootstrap 5 crispy template pack installed or whatever so i had to deactivate that anyways though now let's see what happens if we go back here we refresh and we go to slash login now when i go there notice it brings me to a login page so we have our login right we have this that we've added don't have an account create one here and then we have the login button and the form is automatically generated for us now you can customize this form if you want but i'm not going to do that in this video this is just kind of the default login form that django will provide you all right so now that we have all that this will actually handle signing in a user for us automatically so we don't need to do that manually and once you have users created you can go to login sign in with them and again that will be handled for you now a few other things we want to add here so go to our settings.pi go to the very bottom so just put inside of here two variables first login redirect url so this is where you want to go after you log in so i want to go to the slash home page after i log in and then we're going to change this to be the log out redirect url and where do you want to go when you log out well i want to go to slash login okay so you can change dynamically where you're going to be placed when you log in and log out and then we just want to add a root for slash home now so let's go to urls.pi and let's just add another path and let's just make this home okay so now if you go to home it will bring you to the same page as when you go to the empty root okay let's save let's what's it saying login is not defined we go to settings.pi i think we're fine let's rerun this everything should be good okay so now let's just have a look at something if i go here and i go slash log out notice it redirects me to the login page so i wasn't logged in so obviously it didn't need to do anything but when you go to log out it would log you out and then bring you back to the login page okay so now that we have done all of that we need to be able to create user accounts so to create user accounts we actually need to set up the route for that ourself so we're going to make a new template here inside of registration and this is going to be called sign underscore up dot html and we'll copy everything that we have from login and just place that into the sign up we'll just change this slightly so for sign up we just want to make it so that rather than having login we have register okay and then rather than don't have an account we're going to say have an account question mark and then we'll say log in log in here and then we'll change this to slash log okay uh for the page we'll do sign up and i mean i guess you can make this sign up as well i'm just going to make it register and that's actually all we need for the sign up page okay so let's save that all right so we now have sign up and we have login we now need to go to our views and we need to make a view here for sign up we actually have to write this ourselves so i'm going to say define sign up we're going to take in a request and since when we go to this page let's have a look here we have a form that has a method of post so that means when we go to the page what we want to happen is if we're having a get request we want to render the page so show the html but if we have a post request we want to read the data from the form and create a new account so we have to handle that here so i'm going to say if the request dot and then this is going to be method is equal to post then we're going to say form is equal to and this is going to be register form we're going to write this form in one second but we're going to pass to this the request.postdata okay now otherwise we're going to say form is equal to register form like that and we're going to say return render request we're going to render registration like that slash and then this is going to be signup.html and we're going to pass to this a form which is equal to our form variable now again i know a lot of this seems confusing if you haven't seen this before what we're going to do is create a register form now when you create these forms what that allows you to do is pass post data to them and then they can automatically validate the data for you and you can simply render the form using this kind of uh you know filter again it's probably not a filter but that's what i'm calling it uh inside of a template so now let's create the form and then this will make more sense so inside of main we're going to make a new file here it's going to be called forms.pi and we're going to make the registration form so the way that we do this is we say from django import and then we're going to import forms like that and then we're going to actually extend the user creation form which is the default form from django so i'm going to say from django dot contrib dot and then this is going to be auth and this is not forum this is from django.contrib.off dot forms i want to import the user creation field so user creation sorry form like that and then i'm going to say from django dot and then this is going to be actually contrib and then dot auth dot models i also want to import the user model okay so i'm going to say class registration form this is going to be uh user creation form like that i'm going to say email is equal to forms dot email field i'm going to say required equals true i'm going to say class meta i'm going to say the model is equal to user and then the fields is equal to and i'm going to list all of the fields that i want to be required uh when we sign in so i'm going to say username email and sorry not sign in this is create an account password1 and password2 okay i know i just went through a lot and didn't really explain it but i'm importing forms importing the user creation form which is the default form provided from django for creating new user i'm then importing the user and user is well where we're going to store different users so this is already built into django we don't have to make a user model it has one for us and all i'm doing here is adding a form to the default user creation form called email because i want this form to show kind of you know custom stuff i want it to show the username the email password1 and password2 and by default there's not an email so i have to add that in here by making this custom form so i'm saying okay we're having a registration form overriding or extending the user creation form inheriting from it we then have our email field which we're adding then what class meta is doing inside of here is saying okay well what are we creating with this form we're creating a user and the fields that we want to have from the user model our username email password1 and password2 hopefully this makes a little bit of sense i can't really explain it much more than that feel free to read the django documentation for a more in-depth explanation again just extending this form adding the email field and now we can have our custom signup page and if you wanted to require more information here you can add different fields so you could add i don't know maybe a birth date or something right and then you would just add that into fields here and then you'd have to fill in all of that when you're creating a user and it will automatically be added to the user model okay so let's go to signup.html or sorry views dot pi and now we are going to import this registration form so we're going to say from and this will be dot and then forms import and we're gonna import the register and i called it registration let's just call this register and we can change it here to be register form okay and now we're gonna use this form so in views what we're saying is okay if we have a post request then we're going to fill the register form with whatever the data was that's in the form that we displayed if it's not a post request so if it's a get request then we're going to create a form that's empty that doesn't have any data and we're going to render that as the form hopefully you guys are following let's go back here though let's now go to actually i forgot we need to go to urls and we need to create the signup route so now in urls let's paste in another path let's call this sign up and now instead of use dot home this is going to be views dot sign up and the name will be sign up okay i think that is good now we can go back to our browser and we should be able to just go to sign up so sign up like that and there you go now it brings us to this page so we have username we have an email we have a password and we have our password confirmation and again notice this entire form is built for us we did not have to make this ourself quite nice then if we go log in bring this login page go sign up brings us to the signup page all right so now the form is displaying nicely what we want to do is actually handle what happens when we hit this button so it will validate the form for us but the thing is we want to send a post request and then in the post request we need to create a new user because right now all we're doing is we're just getting the form right we're not actually creating a new user so we need to make a user so to make a user we're going to say the following we're going to say if form dot is and then it's going to be valid so there's actually a method on the form that will validate this form is indeed correct then what i want to do is say user is equal to form dot save okay then what i can do is log in the user now to log in the user we need to import this so we're going to say from and then this is going to be django.contrib.off import and we're going to import login and while we're out add it we can import log out and then authenticate and i'll just show you how we use these slides later on okay so we have a login function log out function and authenticate and now if i go here after i create my user what i can do is the following i can log in my user so i can say log in i can pass my request and i can pass my user so that's as easy as it is to create a new user again we overrode the form right for the user creation form inside of here when we send a post request so from the form on the html we are going to populate the form using whatever the data was we're going to say if form is valid then we will save the user and we will log in okay so now that we have that let me just import redirect and i actually want to redirect the user here so i'm going to return a redirect okay and i don't want url4 i just want to have a redirect to and let's go slash so now they'll just redirect us to the slash home page and i think that should be good for the sign up view so let's now go back here and let's try to sign up so let's refresh the page okay let's go username tim let's go email tim gmail.com let's type in a password let's intentionally mistype the password and then notice it tells me hey the two password fields don't match so it automatically does that for us i don't have to handle that okay let's now type it correctly and let's hit register and when i do that it brings me to the home page because i've now signed it now i'll show you how we check who's signed in but now what we can do is go to retool and we can try to have a look at all of our different users and see if that was actually created correctly so notice here that we have we look at the different tables let's actually search them by table name we have auth group auth permissions auth permission auth user now auth user is what actually contains our different users so what i can do now is just make a request or make a query to the auth user table and view all of the users in that table so if i make a new query here resource query let's call this let's say get underscore users then i can say select asterisks from and then auth underscore user and let's save and run that and notice that i have an id1 i have my password hash i have my login is super user i have the username tim and i have the email and all of the other data like first name last name we didn't populate that but if we wanted to add that to the form we could have and now if i want to view that in a table here let's just drag a table in okay and it actually automatically threw in my getusers.data for me so now i can view my users really easily there you go we now see that user has been created so now let's actually log this user out so let's go log out so now that i've logged out let's just try to log in let's go tim and log in and notice that works fine brings me to the homepage now let's see what happens if i try to log in as tim12 notice says please enter a correct username and password it automatically populates a message on the screen so at this point i have actually showed you how to login users sign up new users and the basic authentication system of django you can see all this stuff is built in like we don't have to write a lot of this and you can go in and customize it but for most websites this is going to be pretty much all that you need so i just want to quickly recap you because that was kind of an important section and i know there's a lot of stuff that we went through here so we started buying urls.pi adding this auth urls right now when we add that it gives us a bunch of pre-built urls that we can use then what we did is we created a login and signup form now in the login and signup form we're using the crispy forms kind of module to allow us to just display a form that's passed to this template so when we went to views for example and we had sign up we passed this variable form and we are able to display that entire form using the crispy form tags in our template then for login for example the root for this is already created so when we go to login it just displays this form and then all of the authentication is handled so it will automatically authenticate us automatically log us in we don't have to handle that again you can hook into that and customize the behavior all you have to do is create a form add your csrf token do something like this and then you can customize it how you like and add a button here to submit the form okay continuing if we go back to views.pi we need to manually handle the signup form just because we want to display our own form right so we created a register form so if we go to forms we have the register form overriding the user creation form we've added email because that's not by default in the registration form and we could have also added first name and last name so if i want to show that to you i could do something like first name is equal to forms dot and then we can just make this a char field and say required equals true and then for another form that we want to show or another field we want to show we just put first name and now if i go back here and i go to this notice the first name field's automatically added right so of course i could add the last name field as well i don't really need to do that it's fine and i don't actually want the first name field so let's remove it but i just want to show you that you can add your own custom fields on there for the user model and you can kind of customize it as you please and yeah that's pretty much it uh from views we also had login and we've saved the form we validated the form but that's how you handle authentication now the logout route is already written so when you go to slash logout it logs you out now though what i want to show you is how we view the current user that's signed in how we get their username how we display that for example on the nav bar so let's do that to do that we're going to go to our base template so let's go to base and in this second part of the navbar here where it just says login i'm now going to write a little bit of logic that will show a different thing if the user is already logged in so we'll show log out if they're not logged in and it will show what is it the username as well as log out if they already are assigned it so for now i'm going to say percent percent i'm going to write an if statement which you can do here inside of jenga i'm going to say if user dot is authenticated then i don't want to show login right so we're gonna put for some percent else here and then we're gonna have percent percent and block okay we're gonna copy this li tag we're gonna put it here except we're gonna say log out and we're going to have slash log out as the link so now we have log out but i also want to display the name of the user so to do that i'm going to say span and this is going to say class is equal to and i'm just going to put this as navbar text i'm going to end our span tag here and i'm going to say logged in as and i'm going to say user dot and then username like that okay and then i'm just going to put a pipe here just so it separates this li tag because these are going to be on the same line okay so now let me save this and let's quickly talk about what we did so user is a variable that's accessible to a template no matter what so we don't have to manually pass this to the template it can always access this user variable so i can check if the user is authenticated now if the user is not authenticated of course this is false and that means that we will show this right we'll just show login now if the user is authenticated we're going to show logged in as and then whatever their username is so you can just access the username and then we'll show log out and it'll bring it to the logout url so pretty straightforward but inside a template you can use something like is authenticated you can also use stuff like is super user has permission i'll show you that in a minute for now though let's go back here and let's refresh and we got an error here it said n block expected and if sorry so when i have end block here just need to change this to end if that's how you add an if statement let me save let's go back and refresh and notice this as i'm logged in as tim if i log out now it shows log in brings me to the login page try to sign in as this guy incorrect so let's change this to tim login and then it says logged in as tim and then i have the logout button okay so our authentication is pretty much handled now we want to start dealing with user permissions and allowing specific users to create posts so actually we'll do creating posts first and then we'll deal with the different permissions so i was just editing this video and watching it back and realized that i missed something in here so i want to jump in and add it so here is the documentation for using the django authentication model method whatever there's a lot of stuff in here i'll link this in the description but it's very thorough and it goes through how you authenticate users how you do permissions i'm going to show you a bunch of this stuff but obviously i can't cover the entire documentation so please reference this if there's something in this tutorial that you're missing or i guess something i didn't cover that you need anyways with that said if i keep scrolling down here it says using the views okay so django provides several views that you can use for login logout and password management now password management is not what i talked about and that's what i wanted to quickly mention here so when you include the urls which we did you get all of these urls login logout password change password change password reset password reset reset reset done and i want to show you that if we go here we have some views that are already built for example password reset uh was it password reset it was password underscore reset so if i go to password underscore reset you see it brings us to this page here where i'm actually able to reset my password now there's also password change like this so obviously these don't look very good so you can override these views if you want to so just like we overrode the login view by making that login.html template you can make templates that have these names and then it will render those templates and display the form and and all of that so i just wanted to show that to you uh you can continue to read this to see exactly how that works but stuff like password reset uh and password changing is handled by django and again the way you have to do this if you want to override the view is you have to create a template in the registration folder that has the same name as this so password underscore change dot html and then show the form like we did for the login page okay that's all i wanted to add in hopefully that is helpful to you again this will be linked in the description please check it out there's a lot of useful stuff in there alright so i've been a little bit all over the place here because there's a lot of stuff you have to do in multiple different files so hopefully you guys are following along okay again i will remind you all of this code will be available from the description so if you can't get everything down at once which is understandable then please feel free to reference the code there copy and paste what you need of course i'm going to write everything from scratch though because i want you to see exactly how everything is done what we want to do now we've completed the base page is we want to restrict page access and we want to be able to create posts so we can do this in really any order that we'd like but ideally we shouldn't be able to access the home page unless we're signed in and right now we can just go there right if i sign out let's let's go back here let's log out and let's just go to slash it brings me here no problem so ideally i want it to not let me go there if i'm not signed in so how are we going to do that well to do that i can actually use a decorator on top of this function that requires that i'm logged in so we're going to say from django dot contrib if we could spell that right dot auth dot decreators import login required sometimes i swear my autocomplete can hear me because it gives me almost everything that i'm looking for whenever i'm looking for anyways we're gonna do here is put login required and we're gonna put log in underscore url is equal to and then slash login now we just need to do this so that we're telling the decorator where to redirect us if we're not signed it so if we are not logged in it's going to redirect us to this login url okay if you don't have that it will redirect you to something like slash author slash accounts slash login which of course is not the url that we're using okay anyways we have at login required so now that i've added that it's as simple as refreshing here and you'll see that it brings me to login page right so if i try to go to home it just doesn't let me go there it just redirects me over here to the login page perfect so now let's log in let's go tim and notice that i'm able to access the homepage right and if i go slash sign up and then i go slash home i'm still signed in and so i can still view it okay so that's as easy as this to restrict page access for logged-in users now of course if you want only specific users to view specific pages uh that's a bit more challenging but we will look at that later okay so now that we've done that we've seen you know the basics on restricting page access let us have a look at how we can create different posts for users and then only let users who created a specific post delete their own post so let's go to models because we need to make a model here for a post now we're going to make a really simple model and to do this we're going to start by saying from django dot con trib dot auth dot models import user because we need a relationship between posts and users so we know which user made which post so we're going to say class post and this will be models.model and we're going to put in everything that we need so the first thing we need for a post is an author and this author is going to be a user so we're going to have a foreign key that goes to our user model and we're going to have on underscore delete equal to models.cascade now what this is saying is that if the user that's being referenced here is deleted this post will be deleted as well that's all that means if you didn't have this then you would have a bunch of posts inside of your what do you call it database that are linked to authors that were deleted or no longer exist right of course you don't want that so we're adding the on delete okay so that's our author uh now we want to have a title the title is going to be models.char field we can have the max length equal to something like 200 we then want a description again this will be a models dot actually we'll go with text field and i will not limit how large this is although you could do that if you want then we want to have two things we want to have created at so i'm going to have a models.datetime field auto now add true yes we want that because whenever you created this we want it to automatically add the time and then we will have an updated at and i'm just going to have auto now and that's going to be equal to true so whenever we update the model it should update this now we're not actually going to make it so you can update the model but just a good field typically to add to your models all right lastly we're just going to add a string method here just so we can view this nicely so we're going to say string and we're going to return the self.title plus and then a backslash n plus and then the self.description just that if we print out a post we're able to view this nicely all right that's it for adding the model uh these different fields you can reference from the django documentation but this is just characters this is text this is the date time i think you guys understand the foreign key is probably the most complicated but this requires that we pass a user object to the post when we make it and then we're kind of linking each one of our posts to a specific author and so we can access like the author's username and all that type of stuff when we view a post okay that's all we need for models now that we have created that model what we can do is just quit here and we're going to run the command python manage.pi and then migrate and this should make a new table now your model and mains have changed they're not your reflected migration okay sorry so first we need to type make migrations so first what we need to do here sorry is make migrations and then once we make the migrations we can migrate so we'll actually apply all of these migrations to the remote database so i'm going to say python manage.pi make migrations the migration is it created the model post okay and then python managed up pi migrate and then that should be good and actually applies it to our database nice okay so now that we've done that let's rerun the server and let's now set up a way to actually make a new post so we have our post model and to make a new post similarly to before we need some form that's going to allow us to do that so i'm going to go to forms and type class and this is going to be the post form now for this form we're going to write it a little bit differently than we did the other one it's going to be forms dot and then this is going to be model form and all we're going to put in here is class meta and we're going to say model is equal to post and then fields these are the fields that we want the user to have to fill in are just going to be the title and the description okay and then we need to import the post model so we're going to say from dot models import post now again what this is going to allow us to do is simply create an instance of this form pass this to a template and then the template will display the form for us that has the title and the description so we'll be able to grab the title and description data and then we can add other things like the author which is required to create a post before we actually manually make the post so now let's go to views.pipe and let's write a view here we're going to say define create underscore post we'll take in request and then again we're going to have a form here on this create post html so we could have the potential method of post being sent to this root so we have post or we have get right so we're going to say if this will be request.method is equal to post then we're going to say form is equal to and this is going to be a post form and we're going to pass the request.postdata so we need to import the post form as well so let's import that from up here then similarly we want to check if the form is valid so we're going to say if the form is valid then what we're going to do is say the post is equal to form dot save but we're going to say commit is equal to false now the reason i'm doing this is because when you save a form as you can see right here it actually will create this entry in the database automatically if the commit is not passed to this so by default commit is equal to true which means when you save the form whatever the model was that the form is connected to so user or post it's going to create that entry in the database so i don't want to create that yet because this oh sorry let's go back here this form is incomplete right i have my description i have my title but i need to add my user to this form as well before i can do that so i have to say post.author is equal to and then this is going to be request.user and this is how you can access the user that's currently signed in request.user okay then we're going to say post.save and when we save the post now it will actually create that in the database which is what we want all right then we can do a return redirect and we will simply redirect to slash home once we make the post now otherwise i guess we don't really need an else because we have actually yes we do need an else we're going to have an else we're going to say form is equal to and this is going to be post form just an empty post form and then we're going to return the render of the request this will be main.createpost we'll make that html in a second and then for the form we'll simply pass our form right so pretty much the exact same thing as signup now for making a post we first want to be logged in right so i'm going to say log in required and then log in underscore url is equal to y let's give me log out this should be login okay so now that we've done that let's just make the createpost.html form now luckily for us we can really just copy the login form or the signup form whatever one we want go new file let's go create underscorepost.html paste that in and let's remove this and rather than log in now we're just going to say post and then the name will be create a post okay nice so let's save that and again that's all we need here because the form that we're passing will automatically handle you know creation deleted deletion all of that type of stuff okay uh function object has an attribute user uh request dot user let me see why we're getting that error okay so i just re-ran the server and everything was good that happens sometimes you just need to manually rerun so i re-ran looks like we're good now let's just give a refresh here and let's go log out now let's try to post uh it says create post not found okay that's a good hint that we need to add the create post url forgot to do that so let's add that let's go here let's just make a new path and this will be create post okay and this will be views dot create post and then the name will be create post okay uh now we have that let's go back let's refresh and notice that it is not allowing me to post because i'm not signed in right so now let's sign in and when i sign in it should bring me to the post page great and i have my title and i have my description and since this is a text field i can expand this make it larger so let's do something like hello world and then hey everyone and this should actually work so let's go post and brings us the homepage now we're not viewing any of the posts right now what we can do is go to retool here and we can now view some of the posts if we'd like to do that so let's write a query that lets us view the post so let me just make that a bit smaller let's write a new query let's call this one go here get underscore posts okay and i'm going to say select asterisks from and actually let me just refresh this here and let's see now if we have a post table and we do it's main post main underscore post is what it's called so let's access the main post so let's go from main underscore post like that let's save and run and we should see that we have post id 1 title hello world description created out updated at and then author id is 1. now author id is the id of the user right that created this post and if we go and look at our users we can see this has id one so we created this with uh tim right now we can do a join operation if we want to have information about the author directly on the post but we'll deal with that later i just want to show you that we do indeed have a post and just for easy viewing here let's create another table and there we go we can now view the post data okay so now that we have ability to create a post we want to view the different posts so let's view them on the home page and then we'll make it so you can delete a post but only if you are the owner of that poster if you were the one who created that post all right so let's go to the home page because that's where we want to view the posts and for home here right now we're just rendering a template but let's grab all of the posts and just display all of the posts so to do that i'm going to say from dot models import post and then i can do something like posts is equal to post.objects.all and i'll just give me all the posts that i have so now i can pass that as a variable so i can say posts is equal to the post and that will allow me now to go inside of my home html template and start displaying all of the posts so to do that we're going to have to write a fair amount of html just because i want this to look decently or these i want this to look decently i want this to look decent so i'm going to write a div i'm going to say class is equal to we're going to write a card and this is going to be margin top 2 and let's end the div and i want all of these cards to represent a single post so i'm going to loop through all of the posts the way i can do that is using a for loop directly inside of here so i'm going to say 4 and then post in posts like that let's just end the for loop before we forget so this is going to be and four okay so we now have a card for every single post inside of the card i want to have the following i want to have a header so i'm going to have my card header and this is going to contain the name of the user who made this post so not post that title but post.author and this is going to be at and we can actually say post.author and i think i can just type user name or dot author might do it let's do that username for now that will be inside of the cart header okay then we want to have our card body so i'm going to say div class is equal to card and then this will be body and then we also want to have this be a display flex a flex row and we want to justify content between and what this will do is push content to the left and right hand side of the card you'll see why we need this in a second but it's for adding some buttons and having them being floating on the right hand side anyways inside of here now we're going to create two divs and the first div doesn't actually need a class we can just have it be a div and we'll have one more now just for simplicity here this div we'll say buttons and this these will be the buttons to delete a post and to ban a user we're just not going to handle those right now and in the first part i'm going to display the kind of content of the post so we'll have an h5 tag i will have class is equal to and this can be card title and inside of this div we want to display the title of the post so we can say post dot and then title like that and sorry this needs to be slash h5 and then we'll just display a p tag that has the description of the post so we can say post dot description and then the last thing that we can do is add a footer for the post that displays when it was posted so we have a card footer let's end that div okay and then inside of the footer we're going to have uh actually we can just make it like this text muted and we can just put the text that we want which is going to be post dot and then this is created at like that okay so let me save i just now need to fix some of this because it always messes it up okay command shift p save and now in home we should be viewing all of the posts one thing i can do is i can check if the posts are empty or not as well so i can do something where right before my end four i just add a tag called empty and what this will do is essentially check if there's no posts inside of post now if there isn't any what i can do is display ap tag that just says no posts yet sad face okay let's save all right let's now go back to the homepage let's refresh and there we go we now see our post and notice i was showing you the buttons are going to be on the right hand side that's why i coded it that way so now we want to write two buttons a button to delete and a button to ban the user but we only want to show those buttons to people that have the ability to delete a post and to people that have the ability to well ban a user so it is a little bit complicated to do that but the first one that deals with deleting a post we can do it in the following way we can go inside of buttons here and we can write an if statement we can say percent percent like this okay percent percent if and we can say if request dot user is equal to the post dot author then we'll allow them to delete the post now we'll also allow them to lead to delete it if they're a mod or if they have permission to delete the post we'll handle that in a second because again that's a bit more complicated so request is something that we should have access to directly inside of the template if we don't we can manually pass it but i believe requests we always have access to so we can say if request.user or actually sorry we can just say user i figure out that in the template we have access to users so we're going to say if user is equal to the post.author then of course they should be able to delete this and we'll check this on the backend as well but this will be our front-end you know display so we're going to make a form so let's actually do this first we'll say form the method here is going to be equal to delete okay and then we're going to have slash form like that and then inside of the form we're going to have our sf token or csrf token keep messing that one up and then we need a button and this button will have a type equal to submit we'll have class btn and then we'll have btn danger which makes this a red button and we'll have delete like that okay uh let me again fix this because i saved and save the format all right so that should be good so if the user is the post.author we have a form we have crsf token we have a button that allows us to delete however we need some way to know what post it is that we want to delete because right now this doesn't tell us what post we were clicking on so what we're going to do is add a value here and the value is going to be equal to the currentpost.id now this is going to allow me to access the id of the post that i hit the delete button for however i need a name for this i'm going to say name is equal to and then the name will be we'll just call this actually we'll go post id okay so essentially this button when i click it it's going to add post id with a value of whatever the id of the post is to the form data that will be submitted as the delete request to this url so now if i go back to views.pi inside of home i can do the following i can say if request dot method is equal to delete then i can say the post underscore id is equal to and then i think this is going to be request dot and i think i can do request.post.get and then post id however i might have to change the type to post or i don't know if we have access to delete we can try this for now so let's just print out the post id and see if that works otherwise we'll have to make a quick fix okay let's try this out though for now we've added this in home we've created the button here that the user can click on so at minimum we can see if it's showing up for the user so let's refresh and we got an issue here it says n4 expected l if else or end if uh did you forgot to add that okay and four ah sorry i need to end my if statement so we have the if right here i forgot to end it so let's end it right here percent percent and if okay and save and now we should be good okay let's go back let's refresh and another error empty expect it and block did you forget this uh okay let me have a look all right another problem we have the n4 right here when the n4 needs to be at the end so i had a duplicate n4 that's why i was getting that so let me get rid of that okay and let's try this one more time let's refresh and there we go it's showing the delete button now let's see what happens if we log out and i guess we need another account to sign in so let's make one joey joe at gmail.com uh let's add a password i'm just gonna keep using the same one so don't forget it okay let's register and now notice it doesn't show the delete button because well joey is not the author of this post can joey make a post let's say hi i am joey hello everyone post and there you go now we can delete this post now let's try it so let's hit delete and let's see so it didn't delete the post didn't look like whoa well that's because we haven't actually written the code to do that but if i come here you can see that i was passing all this stuff post id equals two but nothing was printed out from up high so we're not we're not able to print the post id so it looks like this did not necessarily work so let's change this to be post and let's see if that works now so let's go back here and let's hit the button okay so same thing here it was not printing out the post id all right so i've kind of figured out the problem here is that we're sending a get request for some reason when i hit the um button so maybe the method needs to be lowercase so let's see if i can change the method to that of course i need to make this change again okay let's see if now it's going to send a delete so let's refresh let's hit that and okay it's still sending a get request so i guess that's not a action that's allowed from the form so let's just change the method here to be post and let's save and let's come back here and let's refresh and let's try this now and now it's actually sending a post okay so i guess we just have to have a post here my apologies there guys for some reason i thought we could do delete so now when i do request.post.get this should work however we need to change the request method to be checking if it's post so now let's come back here let's refresh again okay continue and let's sorry let's just do this get rid of all this stuff okay here home delete and it prints out the id of two okay that's what we're looking for all is working apologies about all of the confusion there all right so now that we have the post id what we need to do is confirm that this user owns this post and that this post exists before we actually delete it right so to do that we need to first get the post so we're going to say the post is equal to post.objects.get and then we can get the id equal to post id although actually this needs to be filter not get okay so we're looking for this post id and we'll grab the first element here so we now need to check first of all if the post exists so i'm going to say if post and we'll say the post dot author is equal to and this will be the request dot user then we can delete the post so we can say post dot delete like that and i think that's actually all we need to do to delete the post all right so that looks good to me let's just save this and let's go here and refresh no let's just do this now let's try to delete the post and when we do that the post goes away awesome okay so deleting the post is now functioning uh and yeah there we are all right so now that we know how to delete the post i would like to start setting up the different groups and creating a mod group as well as kind of an admin user who's allowed to ban different users so let's see how we can do that all right so as i was saying we're now going to move on to kind of the user management aspect of this tutorial where we start assigning users to different groups and looking at specific permissions so we're going to create a new group the group i want to start by creating is a mod group i also want to make a default group now the default group is going to be a group that has the ability to make a post and the um what do you call it here the the mod group will have the ability to delete anyone's posts we'll then also have a super user or an admin uh we don't need to manually make this because django already has this notion of an admin and this will have the ability to ban users so mods can delete anyone's posts but they can't ban users admins can delete anyone's posts and they can ban users and then a default user will just have the ability to make posts and delete their own post now with the default user they will also have the ability to be removed from the default user so if they get banned they'll be removed as a default user and that means they no longer have the ability to create posts they can still delete their own posts but they won't be able to make posts so that's kind of what i'm going to set up here and that will give you a good example of how to handle permissions restrict page access all of that type of stuff so to do this is a little bit complicated because we need to first create a super user that we can sign into django admin with and then we need to make some groups and i'll show you how to do it programmatically as well but for now what we're going to do is the following we're going to type python manage dot pi and then we want to make a super user so to do that we're going to type create super user okay uh so making super user we need a username so i'll just go with tech with tim uh we need an email i'm just gonna have an empty email for the password let me type this in okay same thing here and then the super user was created so now let's re-run our server python manage the pi run server and now that we have this user we can use as a regular user account so if i log out i can sign in with my tech with tim user so let's do that and notice this works fine because well the user's been created however i can also go to the admin page and since i'm signed in as a super user i'm able to view the admin page now if you're not a super user you can't view this page so if i log out and now i try to go to slash admin it's going to prompt me to sign in with my account and if i try to sign in with the regular tim account for example that's not a super user notice it tells me i can't do that so i need tech with tim instead okay so i'm signing in with tech with tim and i have the ability to view different users and groups so i can view them here just like i can view them on retool and there's a lot of stuff you can do here in the django admin panel but i'm kind of treating this retool application like my django admin so i don't want to spend a ton of time setting stuff up in here i'd prefer to do it just directly on retool because it's way easier to visualize and see and later when we set up the different graphs and stuff you'll see why you know it's easier to use kind of a drag and drop as opposed to programmatically add stuff to the django app and panel but i do want to mention that you can you know add a bunch of stuff here and customize stuff in here now to add a group i can do it right here from django admin or i can do it programmatically so let's do one here from django admin then we'll do the other one from what you call it uh programmatically okay so let's add a group so to add a group i just need to give it a name so for right now we'll have default now we need some permission right so there's some permissions here related to posts so i can just drag them in so i can do or i can click on them so for example can add post let's add that permission now can view post we'll have that permission as well but change post and delete posts for now we won't have that so as we're viewing the permissions here i just want to mention that every model that you add to django so custom model in this case the post model is going to create four permission objects for by default those permissions are going to be add view it change and delete and you can see that on all the models here we have those default four permissions now when i add a permission here to a group that means that any user or part of this group has this permission however django is not going to enforce these permissions for me so it will know that this user has this permission but it's not going to disallow a user from doing something if it doesn't have a permission you as the programmer have to manually do that yourself so you have to check if you know this user has this perm and if they do you allow them to do something or you don't allow them to do if they don't have the perm so keep that in mind these are just permission objects they're really just internally strings they're saying okay this user has this ability this user has this ability then you as the programmer you go in and you check those now you can add your own permissions as well for example maybe you want to allow a user to update only the author of a post actually that probably wouldn't make sense maybe only the description or only the title of the post you don't want them to update everything you want them to just be able to update one specific thing if that's the case you can make your own custom permission object add that to your user and then you can check for that permission object i'm not going to show that to you here but i will show you pretty much everything else so how to check for the perms and then creating them is relatively straightforward okay so now that we have these two perms here can add post can view post let's save this group here and now we have the default group and if we have a look we can see what permissions they have right so to add a user to a group we can do that from django admin i believe at least so let's try here if i go to joey let's see if i can add him to a group uh so yeah i can click this move it over and then i've added joey into the group that's fine so let's hit save and there we go now joey should have those perms so that's great we can do that right here from django admin i will also show you how to do it directly from retool just so we can have everything on one page and kind of pick what we want to view but of course a lot of the stuff you can do from django admin anyways there we go we've just created a new group we've added a user to that group now i want to show you how you do this programmatically because you're not always going to want to do this from the admin table or from the admin page so let's close this let's go cls and i'm going to show you the code we'd write now this is more complicated but i think it's worth showing so we're going to type python manage.pi and i think it is shell that we're going to type yeah so when we type shell it's going to bring us into an interactive console and we're going to start typing the fault so we're going to say from django.contrib dot off dot models we're going to import group we're going to import permission and we're going to import user so we created that default user now i want to create the mod user okay so to do this i need to import a few other things just bear with me here i'm going to say from django dot contrib dot and then actually not off dot this is going to be content types import and then content type like that no why'd that go away come on okay let's type this out again from django.contrib dot content types import content type uh okay and then this is sorry dot models okay so we have that uh then we want to create a group so to create a group we do the fong we say mod created is equal to and then this is going to be group dot objects dot and then get underscore or underscore create like that and then we are going to say name is equal to and then give it a name i'm going to give it mod so this is as easy as it is to create a group so that should have created groups now if i type mod you'll see we have group mod and if i type created we get true so we've now created a group now that we've created a group though we want to add permissions to it so to add permissions to it we first need to find the appropriate permissions so i'm going to see say ct standing for content type is equal to content type like that dot objects dot get underscore for underscore model okay and then i'm going to say actually model is equal to and then this needs to be the model that i want to get the permissions for so i'm going to type post it's not going to work right now because i haven't imported post so let's import that i'm going to say from main dot models import post okay and now when i run this if i look at ct my content type is main post now you'll see why we need this again there's a lot of stuff i have to code before i get to like kind of the main part but we're looking for the content type of post so that i can now get all of the permissions related to that post so to do that now i'm going to say perms are equal to and then this is going to be permission and then this is dot objects dot filter and then this is going to be content underscore type is equal to ct so now if i look at perms we get a query set containing all of this so what i can do is say perms dot can i look at all okay i mean it gives me the same thing but now notice i get all of the permissions related to my post okay so i have the post for add for change for delete for view now that i have all of these posts if i want to add these permissions sorry now that i have all these perms if i want to add them to the group i do the font i say mod which is my group right mod dot and then this is going to be permissions dot add and then i pick the perm that i want so if i want the ability to we're going to say i guess a mod can add posts change posts uh delete posts view posts i guess we'll give them access to all of them uh i think i don't know if i can pass it all of them or not let's see if i pass asterisks perms i think that adds all of the perms so let's now see this mod and then mod dot permissions and okay i can't view all of those at once but you get the point so what i've just done here is i've added all of the permissions for my post to the mod group okay so i've done that programmatically and now let's see how we add a user to the mod group so to do this i need to get a user so i'm going to say user is equal to user dot objects dot filter we're gonna say username is equal to and then what was my other user i had i guess we'll go to retool to have a look here uh i had where was it users let's refresh this and let's bring this down uh or let's just go next we have tech with tim tim and joey okay tim so that's the other user that we want so let's go username is equal to tim okay so now we have our user and what i can do is mod dot underscore or mod.user underscore set and then this is going to be dot add and we are going to add the user all right the reason i got that issue there is because i need to do user.first and there we go okay again i know that was a lot you're going to have to probably watch that again if you want to see all of the commands but that is programmatically how you add a user to a group as well as how you create a new group and how you add permissions to the group so obviously it's way easier to do it uh from the django admin console but we imported these okay we created our group that's how you create the group by the way very easy get or create and then we had our content type this is just so that we can actually get all the permissions for a specific content type we then have the content tab okay we had to recreate that to import it we then get all of the permissions by filtering by the content type that then gives us a list of all of the perms for that in this case post and then what we can do is say mod.permissions.ad i did asterix which just stands for essentially all of the permissions so i added all of those then i got the user that i wanted to add to the mod group and then i wrote this mod.userset.add and then user.first just because that was a query so i had to get the first element from all right a lot i know let's quit though now we should have a mod group with the user tim inside so if we go back to django admin here and we go to groups we should see that if we re-run the server so python manage.pi run server we should see that we have that group so let's have a look here okay let's refresh and we have default mod nice now that we've done that i just want to write something inside of retool that allows us to easily add users to groups and to view what groups the users are inside of so i'm going to change this here so let's just make this full screen so rather than viewing all of the tables now we're going to be able to view all the users and then it has what groups they're in on one kind of straight line so we'll write kind of a more advanced query to do that so if we're looking at the different tables that we have here in retool we have auth user which we know gives us all our users we have auth user groups and then we have auth user or sorry auth groups as well so if i go back actually to page one we have off group right we have auth user and auth user groups now all three of these tables allow us to determine what group a user is in and this is actually good to look at so let's write a new query here that is going to just get for us something else so resource query i won't name it for now but i'm just going to select star from and then this is going to be off underscore group and if i run this you see that i get the following i get all my groups right so i have default and i have mod okay so that's how i get my groups but the issue is this is not telling me what users are in the groups what tells me that is off user underscore groups so if i save and run this then notice that we have a bunch of id so we have id user id and group id so it's saying the user with id 2 is in group 1 and the user with id 1 is in group 2. so that's not very useful to me what i need to do is write a query that's going to tell me all of my users and then what groups they're inside of so that's going to involve a few join operations so let me show you how we do that so i'm going to say select and then i'm actually going to specify what columns i want so in this case i want the auth underscore user dot username and i want to grab the auth underscore group dot name or auth groups.name okay because that's gonna give me the name of the group and for now that's actually fine and we're going to select this from the auth user table but i need to join this with two other tables so i'm going to say from off user i'm going to left join this with the auth underscore users underscore group on the column off underscore user dot id equal to and then this will be auth underscore users underscore group dot user id okay so let's go on like that uh and sorry let me actually remove this for now and let's actually just select asterisks okay so we'll do it one step at a time i don't want to confuse you too badly so we're selecting everything from the auth user table we're left joining that with the auth users group and then this is how we're joining it so i'm saying okay i want to join every row that has the auth user id equal to auth users group.userid so if i save and run this here notice that we got auth users group does not exist uh is it auth user groups i think that's what it's called let's try this missing from clause ah so i just need to fix this one as well so auth user groups like that let's try this and fingers crossed okay so there we go so now we have every single user as well as their group id okay so if we're looking here right we're getting all our user information like we got before and now we get the user id and the group id as well so what i now need to do is i want to have this group id be associated with the actual name of the group so i know this is a complicated query but let's just continue it one more time so now we're going to left join this again and we're going to left join it with the auth underscore group on and then this is going to be the auth underscore user underscore groups dot group underscore id is equal to and then this is going to be the auth group dot id all right so now instead of selecting star i'm going to select the off underscore user dot username and the off underscore group dot and then this will be name so let me run this all right and group well that's groud that should be group id where did i type that group id like that okay let's save and there we go so now we have username as well as the group that they are in and if we want to we can say as group underscore name just that's not confusing and there we go okay so i know this is a complicated query especially if you don't look at sql but we're just joining the tables together so we get the information that we want so now we see user joey is in the default group tim is in the mod group and then tech with tim currently has no group now it has no group because he's a super user so what i could also do is uh this would be auth underscore user dot is we actually have something called is staff and when we look at this now you'll notice that tech with tim is indeed staff so what i can do is view this in a table now so rather than viewing all the tables here that i have let's change this so instead of get tables we're going to say get user underscore groups like that and then we'll grab that so get user underscore groups okay and let's spell that correctly and now we get our users and the group and if we want to we can rearrange these columns let me just drag this guy over here so now we view the username then the group name okay i've made a mistake in the query sorry guys we need the as group name to be right here okay uh that should be better yeah username group name is staff and then we can move this up if one although we no longer really need this table so let's get rid of this one and we can continue to view the posts as we please alright so now that we've done that i just want to make a quick form inside of here that allows us to change a user's group just so you can see how that works inside of retool so to do that let's drag in a form component okay let's make this a little bit larger and we just want to add two select items inside of here that allow us to select a user as well as to select a group that we want to add that user to and then we have the submit button so we can deal with that okay let's just make these go a bit further all right nice so for the first thing we're going to ask to select a user so we need to have the label here as user and then for this one excuse me we're going to have the label as group now we need these options to be filled in with the user's names and the optional group names as well right that we can add the user to so to do that we need a way to grab all the users and populate them as these items so what i'm going to do is go to the select component here and i'm going to change map and i'm also going to change the name here to be user just so we can access that data later on and i'm going to select a source that i want to map this from so here if i were to select a query like get users right now it's automatically populating a few things in here based on each item but what i can do is have the value of item id sure that's fine but change this to be item dot and then username as the label so let's just get rid of that and actually don't need that as well it could just be that okay and hopefully now i think it's going to show me my username so if i click here i notice i get tim tech with tim joey and then it shows the email as well for every single item so kind of a cool thing let me go back here from sorry guys i need to click uh on the select item over here so i've selected the get users query which is the data i want to use here and then i'm saying item.id item is just every item that i have in the array that's being returned here i'm getting the item username right and the ids we get 132 which is what we wanted for the users then the caption is the item.email and that's fine if i go look at get users we're just selecting star from auth user now that's great but for the groups we want to get all the names of the groups so i don't know if i have a query that just gets the groups i don't so let's make a new one here let's call this and we can say get underscore groups like that and to get the groups i can say select asterisks from auth underscore group like that let's just see what this one gives us i notice we get the id and the name so i could do a similar thing for this select where i just get the item.name however i want to show you that in retool there's something called a javascript transformer and what this allows us to do is actually transform data and kind of have it in whatever format we want using javascript so if i want to get the group names for example i can do something like const data is equal to and then i can say get underscore groups dot and then data and i can say okay well like let's let my return value equal an empty array let's loop through all the entries that we have here so let's say let i equal zero i less than data dot length i could say i plus plus and then i can say something like let name equal data and then this is going to be dot name at i and if you hover over this you'll see that the data that we have here is we have two columns right or two keys we have id and we have name now name is an array so is id so i'm accessing the name key here and then i'm accessing the ith element in there so i'm saying that's the name and then i need the id as well so i say let the id equal data dot id at i and then i can say rv dot push and i could push a tuple in here or i could push an object like name id and then return rv all right so let me just make a quick change here and say i dot name.length just because i was trying to access the length of the data but it's keys right so that's not going to work so let's save this and now if i preview this you'll notice i get my different elements right and it shows me the keys so the reason you do something like this is if you want to transform your data into a different format of course retool can handle lots of different formats with the you know different components you have here but i just want to show you that we have this transform so let's call this get group names like that and now if i go to the select component for the group names let's go mapped and let's just use the get group names okay and then for the value it'll be the id and for the label it will be the item.name and then if i select this we have default and mod so now that we have that we just need to hook up this submit button so that when we press it it will insert a new uh what do you call it user into a group so the way i do that is i write a new query here all right so we have a new resource query here let me just call this insert user group something like that and remember that the table that we want to use to actually have the mappings between users and groups is going to be off user groups so what i can do here is say insert and then this is going to be into off underscore user underscore groups and then the data that i want to insert here is going to be the following let me just look at my code here because i already forget it's going to be user id and then this is going to be group id the id will automatically be populated for us and i'll say values and we need to access values from this form so let's just change the title of this form and some other things here uh let's access this okay so for our form let me click on the form here this is going to be called i don't know let's just call it userform okay and then this is user this select here needs to be group so let's call that group okay so the way that we do this now to reference the values inside of there is we write the following it's give you the name of our form which is user form and then this is going to be dot data dot and then we have first the user and then second we're going to have the user form dot data dot and then the group okay so that should actually be good so now we just need to make it so we hit this button we run this query so let's do that if we click on the submit button we can go and we can add an event handler so where it says event handlers we're going to say add and we're going to say submit trigger query the query is going to be insert user group okay and we can only run when a certain condition is true now in this case i'll actually write the condition and i'll say when and i guess we'll say user dot value does not equal an empty string and when this will be the group dot value does not equal an empty string as well just to make sure that we have some value inside of here uh now it's actually saying that's true so let's say does not equal undefined um okay wait what is the current value uh it's oh no okay so it does not equal no and this does not equal null as well okay there you go so now we won't try to enter or input something if that is null and let's just add a title for the forum so form title let's say change user group all right so we're just about ready to test this i just want to add something though so i'm going to go to this query insert user group and i'm just going to add an event handler here and i'm going to say when this is successful right then we want to actually not trigger a query but let's show confetti on the screen so when this is successful let's show some confetti and let's say when there's a failure here then let's not trigger a query but let's actually show notification so we're going to show a notification and i don't know how exactly it would show the error let's say error like that and then the description can be and let's see what it's saying here insert user group dot air okay so if there is an error then we can display that nice all right so there we go let's save that okay now let's try testing this out so let's go here let's have tech with tim no i want this to be tech with tim come on check with tim select an option let's add to the default group let's hit submit okay it's running and then we get confetti which means it should have been added successfully so if i refresh this here we should now see tech with tim is in the default group which we do see so that is indeed working awesome okay so we've now added that form on retool we're now able to see our users now that we've done that finally let's go back to vs code and let's have a look at how we restrict page access and i guess access the model based on the permissions each user has all right so what we can do here to get started is make it so you cannot access the create post page unless you have permission to make a post so first we will have the at login required decorator but we're going to add another decorator here called permission required so what i can do is simply add this permission required and now right before here i can say app permission required and then i need to put the string name of the permission now the way you access the name or find the name is is going to be the name of your app which in this case is main dot and then you're going to have add and then the name of the model so in this case post now if you wanted to be delete it would be delete i believe update is update and i think view would be view now in this case let's just go with what was it add post okay then i'm going to say the login url is slash login so that if you don't have permission it's going to redirect you there and we're going to say raise exception equals true so that this will raise an exception if you don't have permission okay and that's good for that so let's just test this first of all and see now if we're gonna be able to do this so let's go here to django and let's go to slash okay like that let's try to post and then we can create a post because we have that permission now let's log out let's create a new account that's not going to be in a group and that shouldn't have that permission so let's go susan okay susan susan gmail.com okay let me type in the password and again and let's see here okay and let's go to post and notice we cannot create the post because we don't have that permission now though if we go here and we add susan to that group so let's just do a refresh here just so that the query is going to rerun okay and now we should have susan as a user here okay so i just reran the query down here and once i reran it now it gives it to me so i have susan okay and then for the group let's add them to the default group let's submit okay it's going to take a second looked like that worked so now let's go to post and notice that i have the ability to make the post because i'm now added to the default group great so that is working fine now that we've checked that permission we want to make it so that mods have the ability to delete anyone's post so to do that i can go here instead of use and where i'm checking if the post.author is equal to request.user i can also check the following so i'm going to say or and then i want to check if the current user has the permission to delete the post so the way i do that is request dot user dots and then this is going to be let me just find this has underscore perm and again i can check main dot and then this is going to be this time delete underscore post okay so if the user has the ability to delete the post then i will let them now i want to do the same thing though in my template so where i'm checking if the user is equal to post.author i can also check so we're going to say or or user dot and then what do i have has underscore perm and this would be main dot delete underscore post now it might be a little bit different than that so let me just check uh actually it's going to be the following sorry it's going to be perms dot and then let's go back here main dot main.deletepost so i forgot every single time you're in a template you have access to this perms object and this perms object will simply tell you if a user has access to a specific permission or not so i'm saying perms.main which is my main app right and then dot delete post and well that tells me if they have that permission or not okay straightforward enough let's save and let's just go to retool quickly and let me have a look here again at what user is a mod so tim is a mod so let's sign in as tim so log out let's go tim okay log in and let's see here and well okay that's my own post so i do have the ability to delete it okay that was kind of a fail let's sign this tech with tim and make a post just for testing purposes here let's say hey world okay uh hello okay post let's now log out okay let's sign in as tim who is a mod and i have the ability to delete someone else's post and i guess i could try this so let's try to delete tech with tim's post and it works because i am a mod however if we sign in with susan now so let's sign in with susan you will see that we do not have the ability to delete tim's post because well we are not a mod and then of course the admin they have like the admin user has permission for everything so they'll already have the perm to delete other people's posts okay hopefully that makes sense but that's what we've just done now though we want to make it so that we can ban users so banning users should only be done if you are a super user right so i will show you how we check that so let's actually after this if statement add another and we're going to say if and this is going to be user dot and we'll say is underscore underscore staff okay so we're going to check if they are a staff user if they are staff then we can end the if statement and inside of here we're going to put the exact same thing except this time rather than having the button that's going to delete we're going to have a button that says band so here we'll say fan user and then rather than the post id this will be the user id and we're going to get the post dot author dot id so that way we know what user it is that we're going to ban so that's actually all we need for this and again this will only show if your staff and staff pretty much means you're a super user or your group is a part of the staff group although i haven't shown that again there's so much stuff you could show with authentication and user management anyways we've now handled that so we should now have that button so if i come back here i'm signing this tech with tim so if i refresh i should see the band user button nice now let's just add uh button and then warning just so that this looks different okay now let's come back and let's refresh and now we have band user we can add a margin between them but for now i think that's fine so now that we have that let's go to views.pi and let's handle what happens if we are going to be banning a user so here when we're checking uh we're checking for a post request now the issue is another post request is going to be sent but this one is going to have a different id rather than post id it's going to be user id so we have post id we have post so we're going to have to write kind of another if statement here and say if post id then do all of this otherwise then we're going to try to get the um what do you call it the the user id so we'll say user underscore id is equal request.post.getuserid i'll say l if and then this will be user underscore id then i'm going to say the user is equal to and this is going to be user.objects not get but dot filter we're going to filter by id equal to user id and then get the first user we're going to say if user and the current user so and request.user dot and not has perm but dot is underscore staff then we will ban this user now the way that we ban this user is we simply remove them from the default group because once they're removed from the default group then they won't have permission to what he called to delete posts or to do any of that kind of stuff we also could just remove a specific permission from them but in this case i'll just remove them from the group so that way if there's any other permissions we wanted to remove when they're banned it would just be removed because they're no longer in that group right so i'm going to say group is equal to and then it's going to be group.objects.filter and it's not going to be user it's going to be name is equal to and then i need to find the default group i need to remove them from it now we also need to import group uh so i need to do that from here so that's gonna be from django.contrib it actually was showing it to me.auth.models uh we need to import user as well as group so good job we did that okay then where were we here we have the group now we're going to say group dot and this will be user underscore set dot remove and we're going to remove the user from it and there we go now we also should remove them from the mod group just in case they're in that so let's do this again we're going to say group is equal to and then this will be mod and then the same thing will remove them from the mod group now i believe this will not crash if they are not in the group we also could just put a try catch here right or try accept so we can just do that in case so we can say try accept and just pass okay because well if they're already banned then banning them again you know is isn't going to do anything so that's fine and then accept and then pass okay so that is it for banning a user now the one thing that we need to handle is that by default when users are created they're not added into the um so i need to get out of this here you can't get out of this stem terminal okay so the one thing we need to do sorry is that when users are created they need to automatically be added to the default group so we're going to need to handle that because right now we have to manually add them and i'd like to have them automatically added in now doing this is not extremely simple it requires that we go into our main config here so we need to go to apps and main config so inside of here we need to write some code that's a little bit complicated but i'll walk you through it so i'm going to say from django.conf import and then we're going to import settings and we're going to write a method here called ready now this is going to be called as soon as this app is registered and ready to use essentially and then inside of here it's important you do the imports in here if you don't do them in here you're going to get an error because you need to load the app first before you can import this we're going to say from django.contrib.off dot models import and then import group and then we're going to say from django.contrib dot actually not contrib sorry from db dot models dot signals import post save okay we're now going to write a method inside of here or a function called add to default underscore group and we're going to say sender asterisk actress kwargs like that we're going to say user is equal to quarks and this is going to be instance okay we're going to say if kwargs and this is going to be created then we're going to say group ok is equal to and that's going to be group.objects.get or create name is equal to default okay i'm going to say group dot user underscore set dot add and we're going to add the user to it now i know this is a lot we have one more line here we're going to say post underscore save dot connect and we're going to say add default group and then this is going to be sender is equal to settings dot and then this is going to be auth user underscore model okay let me walk you through this i know that's a lot of stuff to look at so we imported settings and then we're hooking into this ready method again this will be called as soon as the app is ready then we can import these two things if you try to do this before you put those up here you're going to get an error so make sure you import them inside of here we're then writing essentially what we want to happen whenever the auth user model is created so i'm saying postsave.connect now that says okay after this model here is saved what do we do so every time we create a new user we're going to call this function right here and we're going to pass to it a sender as well as quarks now instead of quarks we're going to have an instance the instance is the user model that was created and we're saying if that user was successfully created then we're going to check for the group default so either get it or create it and we're going to add the current user to that group easy as it is i know it looks really complicated but that's what's going on and this happens again we we add this connector so that every time a new user is created it's going to automatically be added to the group it's kind of waiting for something to be saved and then once it's saved it runs this code right there you go so that is how we do that now every user will by default be added to that group and we are pretty much good to go that's almost everything i need to show you although we need to test the band user feature and see if that works so let's run uh our server here so let's go actually back here looks like it's already running so that's good let's now refresh let's log out and let's create a new user and see if they are added by default to that group so we can just go new new gmail.com let's type in our password okay register and now let's see if we can make a post and we can because we were added to the default group nice so let's make a post let's go hello world what is up okay post i'm very creative i know let's now log out and let's sign in as our super user okay and let's now ban new okay so i've banned i'm not getting any feed feedback because i haven't implemented that but that's fine so now let's go and sign in as new okay and now let's see if i can make a post and okay i was able to make a post so that was not working as i anticipated so let me have a look at what's going on here and i'll be right back all right so i've found the issue here the issue is that we did not actually ban the user and i saw that it because if i go to retool here you can see that new is still in the default group so they were not actually banned or removed from that group so what i'm going to do is go here and just change some of this code because i messed it up so rather than objects we're going to do dot get here for the group so this is group.objects.get and i can just say name and then same thing here dot get i think that should fix it because that's the only change i'm seeing for now we also have if user and request.user.staff there is potentially an issue with the user id so let's just have a look here in the home template and make sure we've done this correctly okay so it is user id post.author.id that should be fine let's try this one more time we're going to try to ban the the new user so let's go here let's log out and sign in okay and let's go to new and ban user now let's see if that worked so let's refresh here and notice new is now has the default group moved okay so that did work changes are all good so now let's sign in as new all right and now let's try to post and notice we cannot post because we have been banned awesome okay so that is pretty much all i had to show you related to the groups and permissions now this is a general introduction of course i could spend like seven hours showing you all the built-in features in django there's a lot more stuff with permissions and i'm gonna get you to reference the documentation to see how that works but you now generally know how to restrict page access how to show different features to different people you know how to set up groups i think i gave you a good amount of knowledge to get started here so the last thing that i would like to do here is go to retool and i want to build out that dashboard that you saw at the beginning where we're able to see some you know nice graphs we already have this form that we made but we can see the breakdown of users by their group we also will be able to see the number of posts number of registrations per day a bunch of stuff that you can't easily add to an admin dashboard right so the admin dashboard is useful but retool can kind of replace that for you and just make it a lot more interactive and easier to see so let's start building that out now let me just make this full screen we want to add the following so we're going to add a graph for the users by group we're going to have one for new users per day and then we'll have the post per user um that we're showing i guess so to do that let's grab some graphs there's a bunch of different things you can see here or charts i guess you'd call them uh so let's have this chart okay let's insert another chart where was it all the way down here okay and let's add another one let's go chart and let's drag that in okay all right so for this first chart here uh let's change the data source to b let's use the drop down here this is going to be get user groups okay and we don't want a bar chart we want a pie chart and we want the value labels here to be group name now for the data set we're just going to hit new here and sum now that's what this is doing we have data series 1 okay and the aggregation method is sum which essentially means we're just going to sum all of the different groups that we have right so if we have four default users you know add those all together we get a value of four we display that in the pie chart null just means you don't have any groups that would be like our admin users and then mod of course is our mod user so in this case we have three default users one mod user and one null user now it is worth mentioning that these can overlap like a user can be a default user as well as a mod um that's possible of course but that's it for the pie chart now we can add a title for this if we want and say users by group okay nice and now let's go to the second chart so for the second chart i'd like to see the number of new users we have per day this one is a little bit more complicated to write but let's do it anyways so to do this i'm going to write a javascript transformer because i need to write something that's going to give me essentially how many users i have per day right and that's you know not trivial to write a query for so let's have users per day and the way we're going to get this information is we're going to look at the users table so if i were to run this and we're going to look at when they joined and we're going to put a graph there now this is a common thing you'd probably want to see some information about you know how many daily average users you have so let's write that so users per day so inside of here we're going to say const rv standing for return value and we're going to say 4 and we're going to get the date of and then this is going to be the get users so let's have get underscore users like that dot and then this is going to be date or sorry not date.data and then dot datejoint so what i'm going to do here is i'm going to look at all my date joins these are what they look like i'm going to grab the individual date and i'm going to push that into rv then i'm going to count how many of those dates exist and however many of those dates exist well that's how many people on that date joint so pretty straightforward actually let me just write this out first so string date is equal to date dot split let's split this at t then we're going to grab the first aspect of that i don't know sorry this is date if that's going to give me a preview of it right now okay doesn't look like it but then what i can do is just rv.push and push in the string date okay and then just return the rv so let's just save and preview that and then notice this is what i get inside of my array so now that i have this right they're all on the same day because i'm doing this well today but i can just count how many of those there are similar to the pie chart and just display that on the chart so here rather than get users let's use the drop down here and let's select users per day and okay that's interesting that's not exactly what we wanted we can remove some of these data sets because we only need one data set all right so for this chart here i've just cleared pretty much everything in here and i've selected uh use users per day as my data source now i want this to be bar chart and i need to make a new data set here so i've cleared all those out right so now let's make a new one this is going to be count and what i want to count here is the following so it's going to be users per day dot value so we count how many of those we have and then this is going to be users okay so now that we have that we need to make it so that we have some x-axis values or what we're i guess we can't actually group by we need some x-axis values so the x-axis values here are going to be the users per day dot value so all those values that we have now let's just put this down on a new line just so it's a bit big enough that we can actually see it okay uh would it do to our other chart we'll move that in a second okay so i've kind of just re-jigged this a bit so that's easier to see but we have this graph here right and it's showing us that we had five users on march 18th now of course if we made more users it would show them in different bars but that's fine for now okay let's give this a title though the title should be users per day okay and lastly we want something that gives us the number of posts that each user has so this is a little bit more complicated again we need to write a sql query that essentially will count the number of posts per user so to do that i'm going to say resource query let's have a new one down here um no i want to save that so let's save for query seven we're going to call this posts per underscore user now i can make this pop out so let's just pop this out so it's a little bit easier to see and we're going to say select and we want username and then we want to count the main underscore post dot id as post from and then this is going to be auth underscore user and we're going to left join on main post which shows us our posts right and then this is going to be on the auth user dot id is equal to the main post dot and then author id and we're going to group all of these by the auth user dot id okay so let's now save and preview that and let's go here and actually make that a bit larger notice susan has one post tech with tim zero joey zero and jimmy zero uh jimmy did i create a jimmy user i guess i must have accidentally created one um or oh i'm using the wrong database sorry let's go to jango tutorial let's rerun that and that's better let me make sure that i wasn't using the wrong database on any of the other ones okay no it looks like i was using the right one i just selected the wrong resource okay rerun and yeah that's better all right so now that we have that we're gonna go to this chart here and we're going to change this so that now it shows us well the number of posts per user so we can say posts per user okay for our data this is going to be posts per user.data okay there we go and then for x-axis values those will be usernames but we need a data set and the data set that we want here or data series whatever you want to call it i guess we can say that this is going to be posts and we want to have no aggregation method because we've pretty much already done the aggregation method and then this is going to be posts per dot user.data.posts okay so then we get zero zero one one zero okay that's what we wanted uh it's still showing us the passwords here let's change that okay username there we go that's better that's what i was looking for okay that's what we have so we have susan tim tim new joey we have tim with one pose new with one post and then the rest with zero this is a bar chart of course we could change this if you want if you want a line chart if you want a scatter plot if we want pie chart uh whatever you want although i guess what makes most sense is going to be bartra nice okay so now that we have done that that pretty much wraps up what i wanted to show you for this video so we create a cool retool dashboard that allows us to view the users as well as what groups they're in allows us to view all of the different posts that we have so i'm just viewing them in here but we can also view them in kind of a graph format like this we have the ability to actually make changes on our database and of course i can add other queries for other databases if i wanted to make this a larger dashboard and view some more things now one thing you can do here is you can actually share this right so you can share this as an editor so if you add people to your retool organization then they can come in here and edit the dashboard you can allow people just to view the application who aren't editors who are also in your retool account or organization or whatever it is and then you have public access if you enable the public link then you can give this to anyone and they can go in there and have a look uh you could add password protection whatever so you can share this dashboard with people and that's kind of one of the cool things right is that you could make this for someone in your organization who is not technical and then they can come in and everything's just done for them they don't have to deal with django admin they don't have to set up a local project they can you know manipulate the database as they see fit of course you can also preview this so if you preview the application then we can view it in this mode which obviously looks a lot nicer and you know i can use this as i would before right so i can navigate between here i can change maybe new let's add u to the mod group and if i do that then here if i refresh it will show that now new is in the mod group all right so with that said i am going to wrap up the video here again all of this code will be available from the link in the description another massive thank you to retool for sponsoring this video if you guys enjoyed make sure to leave a like subscribe the channel and i will see you in another youtube video [Music] you
Info
Channel: Tech With Tim
Views: 128,737
Rating: undefined out of 5
Keywords: tech with tim, django, django authentication and user management full tutorial, django authentication tutorial, what is django, how to use django, how to program authentication with django, how to program user management with django, how to code authentication with django, how to code user management with django, retool, what is retool, how to setup retool, programming expert, programming, coding, tutorial on how to use django, how to setup django, postgres, what is postgres
Id: WuyKxdLcw3w
Channel Id: undefined
Length: 140min 3sec (8403 seconds)
Published: Mon Mar 28 2022
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.