Django Real Estate App Using Multiple Users & Databases - Part 3 | Custom User Model

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
all right welcome back guys in the last video we did a lot of the initial setup for our application now in this video we're going to go ahead and start tackling that custom user model and then seeing how we can migrate that model to our postgresql database which is going to be our users database so if i go in my settings right here we have this users database which is this listings users database that we made in postgresql in the last video and then we also have this listings database so in particular with our custom user model we want this database here to manage that model and all that data so first thing i'm going to do is i'm going to close up this urls.pi i don't need that right now instead i'm going to go inside of this user app we made open up this models.pi and start working in here so i'm going to remove this comment i'm going to close that side window close up that terminal and then zoom in a bit and then let's get working on this so to create my custom user model i'm going to need to import a few things this is going to come from django.contrib.off.models i'm going to import abstract base user i'm going to import permissions mixin and i'm going to import base user manager so these are all things i need in order to create a custom user model and this is all stuff inside of the django documentation on creating a custom user model and we're going to see how to utilize these things so first i'm going to make my custom user model itself which i'm going to call user account you can call this whatever you want but in my case i'm going to call it user account since i think that makes sense then inside of here i need to pass in the abstract base user and the permissions mix-in i'm gonna grab this paste it into here grab this paste it into here that way this user account inherits both of these and then i'm gonna go ahead and define some fields i'm gonna have an email field if i can type so email and then this is going to be my models models dot email field i'm going to set a max length to this which is going to be 255 and i'm going to set it to be unique so i'm going to do unique equals true so that's my email field so by default the user model it's gonna be using a username field as its username but i can overwrite this with the username field and i can set that to be email instead which is gonna use this right here then i'm also going to have a name field so i'm going to use a name an email and a password in order to sign up so this is going to be a models dot character field i'm going to set the max length to be 255 and then this i also want to be a required field when you sign up so the way i can do that is by setting some required fields and i can do that with this required fields and that's going to be a list where then i can pass in this name so that way this is required when i register an account now also right here i have the jingle documentation open just so we can take a look at some of this stuff so if you look for a custom user model in the django documentation you should find a page like this and then if we scroll down there's actually an example of the same sort of thing so if i go down enough if i can find it so here we are there's a full example so you have to scroll down quite a bit to find this but right here it shows you the same sort of thing where you have a user model where you pass in this abstract base user and you can also pass the permissions mix in they don't actually do that in this case they just use the base user manager and the abstract base user and then right here you can see these different fields that they set so they have an email and a date of birth in their case and then this date of birth is the required fields that they use here the username field they use as the email and then they also have it is active and is admin flag that they use and then right here they have this user manager that inherits from base user manager where they have this create user which creates a normal user and also this creates super user which the only difference really is like right here you can see it does a self.create user which is this right here and then it sets this is admin to be true and saves that user and then returns it now one thing you see right here is it uses this is admin although if you go into here where you actually can take a look at the user model there actually is no is admin flag there are an is staff flag which designates whether this user can access the admin site then there's also an is super user flag if i can find that i'll just search for it so is super user and then this designates that the user has all permissions without explicitly assigning them so a combination of this flag and this flag is what you can use to create a super user and then as for the is admin i'm not entirely sure if that's a typo here or if that's just some kind of flag that i'm not too aware of but that's what they use in this example here although here when you take a look at the user model itself it doesn't actually show this flag anywhere so anyway that's what we're going to be using to create our super user this is staff and is super user flagged so back in here let's go ahead and continue on so i'm going to create this first of all is active this is going to distinguish whether this user is active and can actually log in so i'm going to do a model stop boolean field for this and then i'm gonna set the default to be true now if you have an application where let's say they receive an email they have to activate their account then maybe you might set this to something like false and then once they activate their account then this gets set to true but in our application it's going to be a little simpler and i'm just going to have this set as default to be true and then i'm going to have it is staff flag and this is going to be another boolean field and by default it's going to be false so there we go these are these two flags here and now i'm also going to have one additional flag which is going to be my is realtor flag so this is what's going to be used to distinguish a realtor and a normal user and also an admin user i suppose and then this is also going to be a boolean field so i'm going to do model stop boolean field and the default for this is also going to be false and then if we take a look at the documentation here with their example right here they have this objects that they set to their user manager and then this user manager is this right here where they have the different functions for creating the user so we're gonna do the same sort of thing so back inside of here right below this flag i'm gonna have an object property that i set to user account manager and i'm gonna instantiate that and then this user account manager is a class i need to define so right above here i'm going to have a class of user account manager and then i'm going to pass this base user manager to this so that it inherits it and then i'm going to define some of these functions so i'm going to have a create user function and then here i'm going to pass in self we're going to need an email a name and a password which by default is going to be none because if you have a password of none then the django cli won't actually create the user and then inside of here i'm going to have a check for if not email then i'm going to raise a value here and it's going to say users must have an email address so once again this is just like they have right here if not email there is a value error where users must have an email address and then the next thing we're going to do is we're going to normalize the email so i'm going to have email is self dot normalize underscore email and then pass in the email so this right here is going to normalize it and then reassign it to this email so what normalizing is going to do is make it in lower case so if you had something like john doe at gmail.com then once you normalize it this capital g is going to be changed to lowercase or if you have something like dot com it's going to normalize this to be dot-com like so now a little catch with this normalized email let's say if i had a capital d right here when you normalize it's not going to change this right here so in order to actually have it lowercase everything what i can do is do email is email.lower and that way i can change everything to be lowercase so that way it's a little bit further normalization i suppose because by default let's say if i had this and i had this right here these would be two different accounts inside of this django application even though case sensitivity isn't something that's done with emails if you sent an email to this address here and this address here it would be sent to the exact same email but with django it treats these as two different accounts so if you don't want that you can add this right here then the next i'm going to do is user is equal to self.model and then to create this model i need an email and then i also need a name so there we are and then i want to set the password now i don't want this to be a plain text password so what i can do is user.set password then pass in the password and this will make sure to hash this password so that way it's not stored in the database as plain text and then i need to save this so i can do a user.save and then when you're dealing with multiple databases then you have this using that is a property you can set and do self.underscoredb so in our case because we're using multiple databases this is going to help us have this get saved to our correct database and then finally i'm going to return the user so there we are this is going to be our first function for creating our normal user next i want to create my function for creating our realtor user so i'm going to define create realtor i'm going to pass itself email name and password equal to none once again and then here i'm going to do user is equal to self.create user so we're gonna be utilizing this create user function right here then we're gonna pass in our email our name and our password that were passed to this function right here and then after that it's gonna create this user for us so we're going to return it so that way we can store it inside of this variable right here and then once we have reference to it i can do a user dot is realtor set that to be true so that way we're setting this is realtor flag to be true for this realtor user and then i can do a user dot save and then do using is self dot underscore db just like before and i already explained this so i won't explain it once more and then finally i'm gonna return the user and then we need one final function which is going to be for creating our super user so i'm going to do define create super user pass itself email name and password equals none i'm going to do user is self dot create user pass an email and name and password and then i'm gonna do a user dot is super user i'm gonna set that to be true so remember once again we're utilizing this create user function which is this one for creating our normal user we're going to save that return that user and then we're going to have reference to that user here where then we can set the is super user flag to be true and we can also set the user dot is staff flag to be true so this is staff flag is going to let this user to log into the admin panel and this is super user flag is going to give this user admin permissions and then the next thing i want to do is do a user.save and then i'm going to once again have this using itself.underscoredb and then return the user and there we are we have our three functions now in place and then down here i'm just going to have one more function i defined here which is going to be the string representation of this user account model so i can do that with str so double underscore str double underscore passing self and the string representation of this is going to be self dot email so these emails have to be a string so this email field right here is just a character field that has some additional validation checks just to make sure that it's an email and there we go now we have our custom user model fully created here so the next thing we have to do is make these migrations so i can do that with python manage dot pi make migrations and then of course there's one thing i forgot to do so let me close this up go into my settings scroll to the bottom so when you create a custom user model you also need to pass this auth user model field right here and then put the path to our custom user model so let me open up that side window so the path to this is going to be user and then dot user account because in our model we call this custom user model user account so again you can call this whatever you want but you just have to make sure that you refer to this name correctly when you're referring to it right here with this setting so i'm going to do user dot user account in my case but if you called your custom user model something else make sure to put the correct name right here so i'm going to save that open up my terminal run my make migrations once again and there we go we created our model user account now i can't migrate to my postgresql database quite yet because remember our default database is empty so if i close this up go to my database settings if i do a migrate right now it's going to try to migrate to this but we want to migrate to our users database so we need to have a router in order to accomplish that so let's now see how we can create this router so to manage routers we have a setting that we can use which is database underscore routers and this is going to be a list and then this is going to be a path to our router so we can have multiple routers i'm going to have one for my user so that's me for the user app and then also one for the listing app so what i put in here is going to be the path to it so the way i'm going to do this is inside of my user i'm going to create a file which i'm going to call router.pi and then this is where i'm going to put in that class and then that's going to be a class which i'm going to call auth router and for now i'm just going to have it like so i'm going to go back here i'm going to put in the path to that so in quotes i'm going to have user so that's the name of my app then dot the name of my file which is router and then dot which is auth router so that's my auth router class and then once i create my listing router i'm gonna have it here as well so for now i'm just gonna have this one route i'm gonna go to this router and let's start to define this so the first thing i'm gonna do is i guess close that side window and then after that i'm gonna have an attribute of route app labels and i'm gonna pass in user so this user right here is my user app so this right here so it has to be the same name and then there's going to be a couple of functions that we can define here so this is all inside of the jingle documentation so the first function i'm going to define is db underscore 4 underscore read i'm going to pass itself model and then hints like so which is a keyword argument so this db for read is going to make attempts to read from our user model go to our user database so that's what this right here is for and then the way that we can make that happen is with an if check where i do model dot underscore meta dot app label in self dot route app labels then i'm going to return users otherwise i'm going to return none all right so what's going on here this return users what this is going to do is it's going to return our users database so we call this specifically users like this so inside of this router you have to make sure you spell this the exact same so this right here is going to check the model that we're trying to read from isn't inside of our route auth labels which is this right here which is going to have our user app so is this model within this app if it is return this database this database is where we're gonna read from otherwise return none so that's how this works right here next i'm gonna define db for write so this is going to make it so that attempts to write to our user model these are going to be routed to our user database so once again here i pass in self model and then our keyword argument of hints and then as for the logic inside of here it's going to be the exact same as this so once again if the model we're trying to write to exists inside of our route off labels which our route auth labels has our user app then we're going to return our users database and that's where our rights are going to be directed to to our users database now the next thing i'm going to define is allow relation i'm going to pass in self object 1 object 2 and then up my keyword argument of hints so this is gonna allow relations if a model in the user app is involved so remember that in django in the last video i explained that cross database relationships are not supported in django so this is gonna make sure that my relations that happen in my models are happening in the context of this route auth labels which includes my user app so only models in my user app are going to be allowed to have relationships between them or i guess another way to put it is also that our user database relationships can happen in the user database only with models defined in this user app so the way that i can accomplish this is with an if check where i can check if object one dot underscore meta dot app underscore label is in self dot route app labels or object two dot underscore meta dot app label isn't self dot route app labels and then if that's the case i'm going to return true otherwise i'm going to return none so this right here is going to ensure that relations happen if a model in the user app is involved so now the next thing i'm going to do is define allow migrate i'm going to pass itself db app label model underscore name equal to none and then my keyword argument of hints so again all this stuff i know it's a little confusing but this is all stuff in the django documentation that way you actually know what you're supposed to pass in here that's how i know so this right here this function is going to make sure that the user app only appears in the user database so that way when we do our python manage.pi migrate that migration is going to go to our user database so i can do that with if app label in self.route app labels then i can return db is equal to users so it's going to be a check right here that's going to result in either true or false and then i can return none otherwise so if this app label appears inside of our route app labels then we're going to do this check right here and then if it passes then we're going to migrate to the database so there we are we just defined our auth router also i should not have parentheses here that was a little mistake i just noticed when you define a class you do not want to have parentheses here so anyway now that i have my auth router class created now let's open up the terminal i'm going to clear things up and now i can migrate so i can do that with python manage.pi migrate and then i want to put the name of my app which is user and then to determine the database to migrate to i can do that with this double hyphen database equals and then the name of my database which is users and then i can click enter to that that's going to apply my migrations so this is going to be users because that's what i defined this to be uh where is it right over here all right so now that we migrated this what i can actually do now is i can open up postgresql i can open up a session in there and then i can list out my databases so these are the ones i have so right now i migrated to this listings users so i can connect to this database with this backslash c listings underscore users so now i'm connected to this database which means now i can list out these tables with backslash dt so now i see all these different things right over here that got migrated and then this user account so this table right here is where i'm going to see my different user accounts so right now if i do something like a select star from user underscore user account and then a semicolon right now we don't have anything inside of here but at least we can see how this data is stored so if i expand this a bit see we have the id the password last login is super user flag email name is active is staff and is realtor so this is all that data that's going to get stored whenever we create a new user so i can press q and then backslash q to exit out of here so i just wanted to demonstrate that i'm going to close this up so now let's go ahead and create a super user so i can do that with python manage dot pi create super user so create super user click enter i can put in the name so i'll do something like brian at listings.com press enter and what is this so if we take a look at this error message we see this django.cor.exceptions improperly configured settings.databases is improperly configured please supply the engine value so why is this happening well because when we try to create our super user we're trying to store it in this default database so what we need to do is we have to specify where we want the super user to get stored so just like we saw with our migrate we also have to pass this double hyphen database equals users when we create our super users so we're going to have it like so python manage.pi create super user double hyphen database is equal to users and that's what's going to make this admin user get stored inside of this users so let's go ahead and click enter to this now i'm going to put in the email so brian at listings.com click enter put in the name so i'm going to have brian i'm going to have the password i'm going to type it again and there we go super user created successfully all right so now that we have our super user created now i can run my server so there we are and then i can navigate and i can open up localhost 8000. and then slash admin slash so that's going to open up this admin panel where then i can log in with my super user so brian at listings.com put in my password click enter and what is this settings databases improperly configured please supply the engine value check again for more details so it looks like we created our super user but we still cannot log in so let's go ahead and see why that is well that is because in this router we need to pass some additional settings so this db for read and db for write so remember this makes it so that attempts to read or write the user models goes to the user database now this right here is checking for this model dot underscore meta dot app label if it's in this self.route app labels that we put here now this right here includes only our user app so what we need to do is we need to pass a couple more things inside of here so let's first pass in our admin so that's a good start so if we pass the admin in here then that way when we try to read and write then it's also going to allow our admin to have read and write access to our user database so now let's go ahead refresh so it appears that we're still having issues here so this admin it has dependencies on some other apps that we also have to include here one of which is content types and another of which is sessions so we need to include these apps right over here now with that when we refresh now we have this django session does not exist so this is now a whole different error so why is this air showing up well let's open up our postgresql shell so i'm gonna double click on this and then i'm going to connect to my listings so i'm going to do a backslash c listings users so i'm connected and then i can list out my tables so here i see that i don't have my sessions migrated so that's what's happening right here so relation django session does not exist so i need to make sure i bring those migrations into this database so how i can do that is first off i can stop running this i'm going to clear i'm going to do a python managed pi migrate so previously when we did our migrate we passed in this user app and then selected our database but in this case i'm not going to select this user app i'm just going to do a migrate to my database which is going to be my users database so again users is this right here which is this database so now i can click enter and i'll see that some migrations got applied and i also see this applying sessions so now when i rerun so i'm re-running my server and then also if i open up the shell here and do a backslash dt now what i'm gonna see is i got this django admin log and also this django session that got added here so now if i go back here and i refresh there we go now we are finally able to be logged into our admin panel now we don't see our user model here because we didn't register to the admin yet that's something i'm going to show in a future video but i just wanted to show some of these little gotchas that you have in order to actually have all this working with the admin panel so that you can even log in in the first place and then one last thing to just kind of clarify we do need to have both of these in here so let's say right now if i were to once again test this out after making those migrations if i go back here and i refresh we once again see the settings databases is improperly configured and then let's say if i pass in just my sessions and then i save here i refresh so everything's fine but what if i go and check out those groups now i get the settings.databases is improperly configured once again so when i actually go to view this content i get that error so the same thing would happen if i register let's say my custom user model in here and my listing model in here if i don't pass in the content types then i'm going to get that issue so we have to make sure we pass all of these inside of my route auth labels that way we don't have any issue when we register for a user log in with the user and also do anything with our admin user and the admin panel so there we are that's everything i wanted to cover in this video and then in the next video we're gonna see how we can create our listing model and then migrate that to the listing database so anyway hope you guys enjoyed the video if you haven't yet please hit that like button it goes a long way to help a channel like mine grow and get recognized so others can benefit from the videos i release as well also i have links in the description that you can check out i have one for an ecommerce course that you can check out if you're interested in learning to develop an application like that i also have a link for joining my web development kings facebook group that way if you want to personally ask me something then you can go right ahead and do that and i will happily help you out it doesn't cost you anything so if you're scratching your head about something then you can go right ahead and ask me to help you out only questions i probably won't answer are if you want me to help you build some kind of personal project as i don't quite have the time for that sort of thing but anything else is fair game you can also post something in the group itself that way other developers in the group can help you out with something as well the group is all about growing your expertise as a developer so if you're interested in that then go right ahead and click that link in the description and join the family also if you haven't yet hit that subscribe button turn on those notification bells that way you don't miss out when i release a new video and i'll see you in the next one
Info
Channel: Bryan Dunn - Web Development Videos
Views: 1,020
Rating: undefined out of 5
Keywords: website development, web development, app development, mobile app, mobile app development, django, REST API, django rest framework, react, node, express, mongodb, postgresql, development, websites, apps, django react app, django react, full stack, mern stack, node react, redux
Id: qI6djFOybSo
Channel Id: undefined
Length: 26min 26sec (1586 seconds)
Published: Fri Aug 27 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.