Learn Django - Build a Custom User Model with Extended Fields

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
okay so if you're familiar with the django user model you'll know that django by default has a very simple user model which only really includes a few fields that might be the username the first name the last name email password so for the majority of projects that you work on you'll probably want to extend this and add more items into the user model so welcome back to a new django tutorial so in this one we're going to be building a new custom user model or developing a new custom user model so we're going to just uh get rid of the django original model for users and we're going to build our own and there's a few things that we're going to add here so instead of having the default username as the actual primary attribute to log into the system for example we're now going to change that to email so we're going to use the email as the username and then we're going to add a different username so that will also be unique in the system so the idea here is that the username has a unique email address which they only use for logging in while they're in the system the user will have a unique username which they can use for making comments etc okay so you can see the flow or the coverage of this tutorial we're going to build a custom model manager which we are then going to be utilizing on a new user model which will build with extended fields and then we go ahead once we've completed that to customize the django admin interface so we go through some of the tips some give some tips and ideas of how you might want to extend the django interface with this new model and then finally we'll do some testing of the new model so something i'll bring in or start to bring into all the tutorials is just quickly give you an overview of the different packages you can just skip this quickly if you don't need this information or you can just refer back to it if you are having problems of course most of the tutorials will have a requirements file but if you're not familiar with that you can see all the different packages that we're going to be utilizing in this tutorial so that if you do have problems first thing maybe is to try and match the packages versions so that you know that you're working with exactly the same packages that i'm showing you within the tutorial so i'm going to start this tutorial on a brand new django project it's always recommended uh particularly if you're new to this type of development that you try this type of development out first on a new project before you might want to start integrating it into a project that's already started of course we are making a number of different changes here which you would then need to update of course your existing project and that can cause numerous sub problems so i'm just going to go ahead and start and build a new application if you look in the commands text here i'm not going to show you this process but if you look in the commands text in the project documentation or the code repo on github there's a link in the description you'll see all the different commands i've utilized here and you'll be able to replicate them once we start doing testing etc you'll see all the different testing commands that i've utilized to inflict or start the testing and so on so by all means have a look at the commands.txt file in the code repository okay so you can see what's happened here we've created a new project and this is going to be the core the main project and then we've created a new project folder or new application folder sorry called users and we're going to be working inside of here so there's no need for your hours here or anything like that this is pretty much all that we're going to need to showcase creating a new user model okay right step one then let's go ahead and just make a new model so you might want to use a completely different model as we uh move along here um you can see that we're in the core or sorry the user's model file and i've just gone ahead and created some different elements here i'll explain these yellow components in a second we'll build those in but i've got a new model here called new user i'm going to be utilizing email username first name start date about of course here you can start to add more i've also included his staff and his active so i'm trying to follow the existing django model in that we know that behind the scenes we will have his staff and is active flag so you want to also um produce that or include that in our new user so we've got two imports here we've got the time because obviously i'm utilizing time right here to set the start date so we're generating a time or a date time field from the time zone package that we're importing in and secondly we're using get text lazy okay so we've not mentioned this before but this is something that i utilize all the time in my models because most of the time you would expect your application online to potentially be translated into other languages so simply put i would utilize this at any point in my project where i think that data might be translated by the end host or indeed we might allow the system to translate the data into the end user's language so if you just read through this uh translation documentation here in django it says here it's your responsibility to mark translatable strings the system can only translate strings it knows about okay so we're not about to translate the fields of the database so we don't need to actually change the names of the fields of the database but where we might want to provide translation is for example if we provide help text to users or for example reference text to fields in the database and so on so i've just planted the seed there by all means have a look at the translation documentation in django particularly the get lazy or get text lazy here and you can see it gives us prov what provides us an example of how to actually port import this in so here we have import get text lazy and then we get as underscore so instead of us writing get text lazy like for example this example here in actual fact we just use as and then the underscore and then we can just go ahead and just change these into the underscore obviously referencing the get text lazy and you can see here that i'm using it on the reference points for the actual fields so this is something that can be utilized within the system and be translated obviously like i said i'm not actually translating the actual name here email because then there'd be problems the field's always going to be called email in the database okay so other things to point out at this point is the fact we've got the email as unique and also the username as unique so we are expecting those two fields to be unique in the database and then we have the first name which should be probably defined as unique unless we define it as blank equals true so that should now be okay and we can now move on of course you can start to build this up as much as you like and add some more fields etc so this is where we are customizing this is the new user table that we're now customizing so like i said by all means add some more fields here okay so now we need to start thinking about actually integrating it within django or telling django that we're using a custom user model so here's some information in the customizing specifying a custom user model essentially what we need to do is we need to utilize abstract base user and we need to extend from there so that's what we need to do so we need to first of all just import this into our project so we go ahead and we're just going to import from the auth models the abstract user base so extend that shortly but we then just need to add that or drop that into our model to extend from it so you can see we're adding our new fields so as it specifies here we need to define the username field so this is going to be the unique identifying field that we're going to be utilizing for our new user model now if you remember the default username field is username so obviously we want to change that to email so let's go ahead and just add that first and then that's the first parameter that we need to set so next up is the required fields so this essentially is a list of fields names that will be prompted when the user creates a new super user so because we want the super user to also fill in the username or to complete the email username first name for example we also just need to specify that so let's go ahead and specify the username notice that i've not mentioned email here simply because there's no need to because you would think that by default that would be a default option so because username isn't a default option i'm just going to add that into the required fields then specify that when we create a new super user we also have to complete the username because it is a unique key that needs to be completed by all users okay so let's just finish this off by the dunder string here we're just going to return the username by all means you could return the email and so on i've just selected the username so in future tutorials we'll go through potentially different permissions that we can define straight off here but what we're going to do is just utilize the default permission mix in and include that in the actual creation of users so that we can hook into the and utilize the permission facilities that django has so we just move across an import abstract user and then the permission mix in so we need to just also add this in so this won't work in actual fact if we don't utilize the permission mixing so i did previously make a well i have made a video previously about the permission mixing so the final step here before we add our in custom manager is to include the permission mixin so as it says here to make it easy to include django permission framework into your own user class we django provides the permission mixin so here essentially what we're doing we're just hooking up the users to the django permission system or framework so we need to do that by just adding in the permission mix in here and then we're just going to include it in the class here so yeah to summarize this isn't going to work unless you add the user to the permission mixing so it is a necessary step okay so now we're going to write a manager for our new custom user model so if you read the document it says that we need to use the user manager if we're using the django default fields that are defined in the default user table but because we're not then we're going to and we're defining our own custom fields then we're going to need to use the base user manager so while we're doing that why we need that is because we want to use these methods here the create user and the create super user and by doing so essentially we're just going to tell django that we're utilizing new fields so we've got more fields in our authentication table so let's bring in the base manager so we need that and then we go ahead and create a new manager so we're going to call this a custom account manager and we're going to extend from the base user manager so here we're going to need two functions like i've just shown you so first of all we create the create user function and deal with what needs to happen when we create a new user and in addition to that we're just overwrite or just flesh out what we need to do if we want to overwrite the super user when we build a new super user so let's just first concentrate on the create user so let's just pass in the details into this function so we want to first add in the self email username first name and password so that's essentially what the user is going to have to complete to sign up to the system and then in addition to that we've also got the option of other fields so we can include that in so now we've got that in place so let's just flesh out this so we're going to ultimately return the user so we want to first of all just deal with the email address so we're going to normalize the email so as it says here we just basically normalize the email address by lowercasing the domain part of it just to prepare that then we take in the user details here we've got the email username first name and then in the other fields that we may have defined and then we go ahead and create or set the password and then save all that data and then return the user so here we can perform some validation checks and this will help support our testing so let's just validate for example the email so if um we don't include an email you can see here we're going to get a value error you can see that i'm going to use the get text lazy so i'll start off like that so you realize what's going on if you've forgotten i'm using the the underscore and then it just says you must provide an email address so that's just an example there of other validation checks you might want to perform it's going to produce a value error and like i said we'll utilize that in our testing okay so now let's move over to create you super user so this is what's going to happen when we create a super user so we're taking self again so we want the cpu to enter the email their username and their first name and a password and then we're going to collect any other fields so this is an example of other fields for example with the super user we want to set the is staff to true and we also want to set the super user to true that's obviously a different process than if we're just creating a normal user so we go ahead and also activate so we set them to is activated now notice that um down here that the normal user i've set to false when they create an account so the reason why that is because i'm presuming you may have some sort of secondary check for example an email will be sent to the user they need to click on that and then that activates their user and they can then log in so that's why the original user is set to false in this example of course you can set it to active if you want if you don't want that additional step in your system so let's go ahead and create some um checks here so we're just going to check to make sure that the staff has been set otherwise we're going to produce a value error so again we utilize this in our testing and check this in our testing and again we do the same thing for um the is super user if it's not true then we're going to produce an error and then we'll just return that so self.create user and then we just pass in everything we've um that we're returning there we go so that's going to create a super user so let's just take a look at this uh if we go into the manage pi and then uh create super user we seem to have a problem at the moment so it says no such table off user so there are some a few other steps um in case you have done that and you're wondering what the problem is there are some other steps that need to be taken here so we need to tell django now the fact that we're going to be utilizing this table then obviously we're also going to need to migrate this table before we can get it to work so let's remember first of all that our model is called new user so we need to tell django that we're using this model now we haven't actually told this model to utilize this manager yet and remember we need to do that so um in actual fact i've moved this in the wrong place haven't i so let's just make sure that this function here is actually inside of the class and of course it just needs to be moved across okay so make sure that apologies that was in the class so that should be in the custom account manager class so now we've got our new two functions here create super user and create user we can now add this to our new user so to do that we simply just say objects equals and then our new custom account manager so we're just defining the fact we're using a new custom manager so let's just go ahead and put that there move that across so we define the fact we're using an account a custom account manager so that's been pulled in there and then we can go ahead and then go into our main project folder and go into settings and then we need to tell django that we're utilizing this new model so here we're going to define the auth user model and then users that's the uh the new application and then the model is the new user model okay so let's just double check to make sure that we've actually imported the project so we need to install that so this just for users so we're just adding this into the installed apps so at this point we should be now ready to test this out so what we can do is just go ahead and do a dry run just to make sure that everything's going to work it looks like um we were able to migrate this data so let's go ahead now and actually um make migrations and then of course we want to migrate so at this point there shouldn't be any problems okay so i'm going to go ahead and just try and create this new super user so this isn't going to work just yet and i'm just going to ask you why you think that is so let's create create a new cpu user and so it looks like it's working okay we're going to take in the username the password and i'm going to get an error so it's missing one required positional argument so just take a look at the code for a couple of seconds if you can spot the problem i did mention it at the start of the tutorial and then one of the different parameters that we set um actually defines what we're going to make the super user fill in so at the bottom here if you remember the required fields so we defined the username but we haven't actually defined the first name so let's go ahead and just add that in first name and let's just try this again and just remember that if we move up here we are actually taking the first name in to the createsuperuser and we are expecting it at the bottom here when we create the user so let's just try this again so at this time we're actually typing in the first name which didn't happen the first time we tried and then the password and there we go so let's just take a look at what this looks like let's run the server and log in so if we go ahead and log in um we should have we should be able to log in now at least but the fields in the admin area probably won't line up to what we need so first of all obviously we need to actually import this in the actual model um because it's not available at the moment the reason i'm showing you this because if you remember the default django admin so the default django users automatically get a will appear in here you don't actually need to add them to the django administration so let's go ahead and go into the admin so again we're in users we're going to go to the admin and now let's just add our model so we're going to just start off by just adding the model so we've add the model now to the admin and we refresh and we can now see the admin model or the new user model that we created so if we go in here we should have one user that's what we just created the super user you can see that this is looking a little bit bare there's no other information so we need to potentially add some more functional information here so if i go into the user we can see that we've got the groups that we can apply and so on looks very similar and you can see down here we do have the username and first name and the about here so that is being picked up automatically with the different or the new fields so this is what's going to be completely different or it is different from the original users table you can see that we still have his staff and active so we do have a functional view but we can definitely change this to make it a little bit more functional for us now if we try to add a new user notice what we're seeing here when we try and add a new user oh is a bunch of stuff here in actual fact but again we could probably customize this um it does have all the fields so we start off with the password we can define super user status the group's email username first name about us but potentially we could change this around to make it a little bit more a little bit more functional for our needs so if you're not interested in customizing the admin configuration here then by all means just skip this step and if you're interested in the testing then just move to the testing phase of this tutorial but essentially all i'm going to do now is just go over and give you some idea of how you might want to customize the interface so i'm going to build a new class here where i built a new class here called user admin config takes in the user admin and then we've gone ahead and add insight register we've got taken in the new user model and then the user admin config so we've titled that up and now we can start configuring so let's start off by ordering all of the different users and defining what we want to actually display so here we have ordering and list display so if we go back into our page and we refresh we can now see we've defined what we want to display here email username first name is active in his staff and we can now also order it by in this case start date by ascending or descending however we want to display the ordering so maybe we need some sort of search facility in our admin so we add search fields email username and first name so i'm going to be able to you're going to be able to search based upon those fields there so now we have the search facility so typically you'll want to filter so at the moment we've got filtered by staff cpu user status and by active so let's go ahead and define a little bit of filtering so we're going to be able to filter on the email username first name is active and his staff so that's the filter list so if i refresh now you can see we've added some different filters okay so if we go into the user you can see that in actual fact um there's a bit of a problem here so let's go ahead and just define some new fields here so what we're going to do now is define the field sets so here you can see i've got three areas i've got the top section here i've got the permissions and i've got the personal information so i've separated this into three separate areas so if we go back and refresh we now see we have three separate areas top area here permissions and personal which i've just defined so it just nicely displays everything that i might want to see of course it is functional beforehand we saw that everything was there but this just looks a little bit more tidy and maybe fit for purpose whatever that might be in your application so it is possible to actually change the styling right here say for example what we can do is import the model and then use the form field overrides and then define some form-filled overrides in this case for the text area so that's something else that we can add and then finally what you might want to also change is when we add a new item so you can see it's broken at the moment because we've made some changes so let's just go ahead and define that so we're going to add a field set so you can see here we've got classes wide fields email username first name password and password two so those are the fields that we're going to define is active in this staff is going to be available when we create a new user so if i refresh you can now see all the fields in place in the particular order that i've set email email username first name password notice that this is in bold because it's defining the fact it's a mandatory field whereas first name isn't mandatory here we could also add the bio and any other fields that you want to include that's in your model so the final step here is we're just going to go over some testing of this model now we're going to be utilizing coverage to do that and we suggest some other testing that we can do on the model so let's go ahead and first install the coverage package and i'll just go through that again if you're not familiar with that so so we've installed coverage and then the next thing to do is just to run it so here you can see i've created a command where we actually omit the vmv server or sorry the vmv or the virtual environment folder so if i do tests on this folder what's going to happen is it's going to look into the virtual environment folder and do the tests on that as well or to find tests that need to be done in that folder which isn't ideal or needed in this situation so if your virtual environment folder isn't here then you're not going to need to omit that and obviously if you've got other folders here then this is obviously the way to do that so i'm going to run coverage this is going to give me an idea of what tests i might need to run so now i just run the coverage html and that's going to create a new folder here called html cov inside of here is a index file just go ahead and run that index file in your browser and it should look a little bit like this so you can see here that for example our users model is missing 16 tests there's only 54 coverage so here we are so this gives us an idea if you're new to testing or what potentially needs to be tested of course if you're going to take other testing approaches you've probably done the testing first before you actually built the model but for now we're just going to work this way so we've got 16 missing tests so now let's go ahead and think about what we need to test how we're going to test it so that we can get this down to a 0 and 100 tested so if we go into the users and there should be a file here called test.pi so if there isn't then just make it test.pi and then we're going to import the test case and start from there okay so back into the manual says referencing the user model so whereas before we may have referenced the user model slightly differently when we import the model into one of our views etc here because we've made some changes and we're using a different user model we're going to reference the user model by get user model so in order to do some testing we need to import the our new model so that's done by the contrib auth and then we're importing like i said get user model because we're using a custom model so that's obviously being picked up by our settings file so in the settings if you remember at the bottom we added our auth user model as users.new user so that's where it's all being connected so let's go back into testing so we need to add that in first and then we're going to create our new test case so let's just quickly run through this so we're going to create a new function here called test new super user so that's essentially what we want to do first we want to test the super user so let's go ahead and create the database or get the database and then we're going to create some new data remember we're using the testing database not the real database here so we're going to reference this as super user and you can see here we're going to create some data so we've manually created some data for our database we need the email username first name and password remember that matches the model and what's expected from the super user when we create a new super user and then we go ahead and do some testing so we use the assert equals here so obviously if we create a new user the super user that's the database and in the email inside of this new entry in the database it should match what should equal to test user cpuser.com so this is going to test to see if the test user has been successfully entered into the database and then we can do the same for the other items the username the first name and password test to see if that's been inserted correctly and then we can test to see if it's actually a super user so when we create a super user is it actually being assigned super user so we can test for that so assert true so this should be true so super user referring to the user we just created is super user so they should be super user and then we then test to see if they're staff and then we assessed if it's true if they're active so that should be true and then what we can do is just assess the string return string so if you remember in the models we're just going to test this here this done the string method here so we're just returning the username so we should be returning the username when we create a new user so go back into test so here the username is username so if we created this user in the dunder method here we should be returning the user name so the username is the name of the user apologies um if that wasn't clear so these string items here um attributes are actually what we're entering into the database so that would be whatever um first name and so on so i've just used um username first name and password so we test for that okay then we can then test some more things so this is uh going one step further really whether this is needed um just to get you to start thinking about what else we can test now if you look in the model what we've done here is we've created some well we've raised some value errors if certain conditions are met so we can utilize these in our testing so for example if we were to test this it should raise a value error and that's what we're checking for and that's what we're capturing now in this test so with self assert raises value error we're going to basically pretend we're going to insert this data here into the database and it should cause an error so the question is why should it cause an error apologies if it's too small but here it says is super user equals false so obviously it should equal true so we're testing for that condition here so super user is true so we're raising this value error here cpus must be blah blah blah and that's what was essentially testing for right there okay so then we can go ahead and create another value error for the other tests we have in our model and this time we're testing for example um raises the error sorry search raises value error so where's the value error here obviously it's is staff equals false so again that just matches the model and so on so we can then go ahead and test some more things if we wanted to if the email was missing and so on and so on if we wanted to but that's just some examples really for you to start thinking about what you might want to test there and then we go on and test the user so the user is slightly different and what we want to test because although we enter the same information so we use this time user test user and the items um but this time if you remember we don't set the user to super user so first of all we just test their email to make sure that that equals testuser.com and we can do the same thing for username first name so we do that and then we just test to make sure that the user isn't super user so we say is cpuser that should be false so assert force so that should be true and then we do the same thing as staff and then active so remember the active should be false by default when we create a user remember why i did that was because when we create a user my system's going to have a second step where i emailed the user they need to click on that link that links takes them to a page that authenticates the user and then sets the active is true and then they can log in so they won't be able to log in the system unless the user is active okay so let me go ahead and do an assert raise value error so the same type of principles here i'm going to test that if i insert some data and i miss some data out that we cause an error and so i'm going to capture that so the email is missing and the email i'm busying sorry and there we go so there's just some simple tests that you might want to create on this model okay so let's go ahead now and run the test again so we coverage run so we've done some tests we've ran two tests of the tests we've run or obviously the class user account tests the function here test you new super user that's one test and all the different items and then we bunched all these tests up here and the test new user so there's no problems there so let's now go into the coverage html and we should now be able to open up the page again so this is where we were so i just need to refresh this page we had 16 missing refresh we've gone to 100 now and there's no missing tests so obviously this coverage package provides us a guidance it doesn't always provide us or give us guidance to every test we might want to do or choose to perform but it is a good way of starting testing a visualization of what needs testing in your application okay so there we have it we've created a new custom user model in django we've now changed the system just change django so that it utilizes the email as the old username in the system so that's the key or the main primary item that the user utilizes to identify the user and of course we then made the username mandatory still so when we create a new username or user sorry they need an email and a unique username so at the moment we aren't capturing that that's one point that you could look at this and improve upon and we probably need to then move into the back end and create a view of actually building this because remember what we've done is made a model we haven't actually instructed django in the view for example the logic that's required to actually um maybe perform some changes or perform some actions so let me just clarify that so um for example if we go into uh if we create a new user if i can just grab that okay and type it in so if we were to create a new super user we will find that django will still offer us errors so in the background django is still uh in control with utilizing the similar code if we using the the original user table um still providing us some errors and so on so we can obviously manage this um and something that we will want to manage is that for example um i won't set up now but if you were to go ahead and create two users and make the username remember it needs to be unique in this system the same then you would get a slightly different error it won't django by default won't capture that error and display it like it would do if you had an email unique issue so that's something that we'd need to create a custom view potentially for and that's something we can definitely do in another tutorial of course that type of thing can be captured in your form and in your view when you're actually building the authentication system and the the interface um for your system so that can be captured elsewhere of course okay there we go um hopefully there was some value there and you've learned something new and you can now go ahead and start implementing that into your applications so this represented um a little bit of a deeper tutorial in that i provided a little bit more testing or will try to apply testing or give you guidance on what or how to test in future tutorials now if you're not too sure about testing i did start a testing tutorial series so have a look at that series also to kind of give you some additional guidance on testing again thank you for listening and for your support so far and hopefully i'll see you in the next tutorial
Info
Channel: Very Academy
Views: 95,656
Rating: undefined out of 5
Keywords: django model, django custom model, django tut, django tutorial, django 3, djangoproject, django examples, learn django, django beginners, beginners django, django framework, django 2020, django example, AbstracBaseUser, PermissionsMixin, BaseUserManager, django custom user model, custom user model django, abstract user model django
Id: Ae7nc1EGv-A
Channel Id: undefined
Length: 39min 42sec (2382 seconds)
Published: Mon Sep 07 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.