Django Rest Framework & React Tutorial: Learning Management System (Blackboard / Moodle Clone)

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
welcome to the start of a new tutorial series and this is called teach me Jenga which is a project built with Jenga and react showing you how you can work with multiple users in a kind of mock online system where you can create assignments fold them in and see the results of those assignments on your profile and so this is the finished product of that project and what I'm going to do is just walk you through what it looks like so you get an idea of what we're actually working towards in this tutorial series so I'm gonna go ahead and login and I really have a user created for this and we don't have any assignments just yet so we'll go ahead and create one so we'll give it a title as this is the first assignment we'll set the question to be is this cool also the answer is yes and then we'll add a choice where the first one can be yes and the second one can be no and then we can add a question and I'll say this one is Django is awesome we'll say the answer is true then the choices are true and false and then we can submit this and now we have our assignments an assignment that is loaded here and we can click on it and we see we get the questions yeah and we've only got two questions so we've got is this cool we'll say yes go to the next one we'll see Django is awesome and let's say I want to go back and I'm actually going to change my line so we'll say no this isn't cool go forward Django is awesome we'll say true and we can click Submit and if we head over to our profile you can see we got 50% for that assignment and that's because we said that Django is not cool whereas the answer was yes it actually is cool and so before judging how complete this project is in terms of validation and seeing detail views and thinking there's a lot more stuff to be displayed and that this is really just too basic you'll be surprised as to how much actually goes on in the backend to get this to work and so we're going to be jumping into a whole lot of customization of serializers and and a lot of react as well so this is what we're going to be building in this project where the two different kinds of users were looking at our students and teachers only teachers can actually create these assignments and only students in theory should be allowed to answer these assignments and so we're going to walk you through the process of creating this multiple user system and let's get started with it now so to get started you're going to want to open up vs code I've got absolutely nothing here an empty directory which we'll use to store all the project content and to get started we're actually going to clone something from our github page and this is a boilerplate project that we created for getting started with Django and react and that is here the Django react boilerplate and this is just to help getting started with adding projects that are built with Django and react because it seems we're going to be doing this for quite a while so I'm just going to grab this URL here and we're going to clone into this repository so we'll just say git clone and that will bring this repository into this folder and so there we have it we've got the vs code project settings we've got a home directory which is basically our Django project and we are currently using three different settings files depending on whether you're in production or development and then we have a source folder which has a basic react project setup as well now I'll link a video showing you everything that's contained inside this project which we covered in one of our videos showing you how to set up authentication between Django and react so everything in that video we basically took and just compiled it into a boilerplate repository so that we could just pull that easily so we don't have to keep on repeating ourselves that way we already have a nice setup to get started with and we can get working from here so what I'm going to do is just bring all of the folder contents inside this directory that I'm working with and there we go now I'll just clear out the terminal and we can take a look at what we've got we've got the EVs code settings which basically is just setting pilant and the Python path virtual environment path and some files to exclude in RVs code editor we've got the home directory which has a base settings for all the installed apps middleware templates and some other things that we'll need for both development and production and then in development you've got the allowed hosts being our local host debug being true the wsgi application for development and ADB sqlite3 database setup with the local host of 3000 being in our course origin whitelist and then in production we've got our domain which we would need to add the different wsgi application for production a database setup for Postgres which we don't actually have those credentials set up just yet but we've got the configuration there we've got both password validators and the static files storage for when we use white noise and this is all with the intention to eventually post this on Heroku that's why we have a proc file here but we'll get into that towards the end so we also have the source folder which currently has our App J's which is auto trying to sign up we're using react redux hence these maps data props and map dispatch methods that we're connecting to our app we've got a higher-order component which basically returns the children of the props that are passed in and we've just got a layout a login and the signup container which again also comes from that video tutorial on authentication with Django and react and so what we want to achieve in this video is basically to set up the Django rest framework rest auth which is what we're going to use to authenticate users on the backend but we're going to need to customize that if we want to actually have our own custom user so we're going to create our user we're going to create the serializers for that user and show you how you can customize the rest off to allow for those users so we'll get started by opening up the terminal and just creating ourselves a virtual environment which we'll just name virtually envy and there it is we can then activate that and we'll say pip install - our requirements txt and we'll open up another terminal here to install our node dependencies so just run NPM I and we can get started with creating ourselves a user's app and this is where we're going to create our custom user so I'll say Python managed up I start app and we'll say the name is users and we can go into our home directory to settings base top high and inside the installed apps we can scroll down and add our users and with that we can close base top pie and we'll go into our users app here and we'll go into the models and what we're going to do is import the abstract user which comes from Django's contrib earth models so we'll say from Django but contrib all top models import the abstract user now see you get two types of users that are prompted one is the base use and ones the abstract user now the abstract base user will require a lot more configuration I've also covered this in another video where we actually use the abstract base user to create our own custom user and show you how you can link that up to be the default user of your site whereas if you use the abstract user it's actually a lot simpler so we're going to go ahead and use that we'll add class here and call this the user which inherits from the abstract user and basically what this means is that it has all those attributes like user name password email all of that configuration is done for you except now you can add the fields that you particularly want to actually add that will make your users that much more unique now in our case we're going to store two kinds of users we're going to have a student and a teacher you could be both at the same time but we're not too worried about that and so the way that we're going to handle that is by adding two fields on the user and these are going to be boolean fields so we're going to have the is student which will be models boolean field so either true or false and then we'll have the is teacher which is also a models boolean field so that means is that when we create the user we're going to need to pass in whether this user is a student so either true or false and we need to pass in if it's a teacher and then we'll just say define the string method which takes himself and we'll say return self dot username because remember this does inherit from the abstract user that is our base user and that is what we'll be using when we create our users now what I'm also going to do is define another class here which is the student and this will just be a model stub model and all we're doing is basically assigning a one-to-one field with the user so that instead of working with the base user that we created here will work with the student model when we need to refer to an actual student and we're not going to add too much configuration to this model but it's just a little bit more convenient because here on the student you could then pass in a lot more other fields like what classrooms they belong to what grade they're in etc you could do a whole bunch of things like that we as the user you just want to define whether that user is a student or a teacher that's the whole purpose of this model here we'll just say that the user equals to a one-to-one field with the user that we just created here and we'll say on the needs equals two models cascade so that if the user is deleted then their student is deleted as well and then we'll just say define string which takes in self and say return self dot user dot email for example or user name we could do as well and so with that we then need to go and tell Django that our default user is actually inside out users app so we're going to go into the home directory to settings based our pie and we go all the way to the bottom here and we'll just say that the auth user model equals to users dot user so basically what it's saying is look inside users dub models and find the user model that is our default orth user model to use when authenticating users and I'm also going to add one more setting here which is for unique emails so we'll say that the account unique email equals to true basically this will ensure that we don't get any duplicate emails of our users and like that we can now try and make migrations so we'll just bring it up to terminal will say manager PI make migrations and we see we get create model user and create model student and then we'll say manage the PI migrate to actually migrate those and we also get the base migrations for the entire project and now if we were to try and create a super user then you'll see that you'll actually run into an error because it's going to use our custom user which has two extra fields on it so it's going to tell you that is student cannot be null and his teacher cannot be null in that user so to create an admin user we're going to need to create it through the Python shell so we'll say Python manager pie shell and here we'll say from users table models import user will say that a equals to a user will say that a dot user name equals to admin a dot password equals to let's say dude one two three we'll say a dot is staff equals to true so that it's a staff member and a dot is a super user equals true as well and then just say dot save and you see that it gives us the users user that your student cannot be null so we say a dot is student let's set it equal to false and we'll say a dot is teacher equals to true and now we can say a dot save and now it's correctly saving and if we were to say user objects dot all then you can yet a query said responds with the user of admin so we'll exit out of that now and let's call Python manage the pi run server so we can actually run the server and view it in the browser this is what we have by default because we already have a build directory appear in our project we have the build directory which is what's being referenced inside our based settings to use as static files so we could actually come here to the login and let's try and login with our user will say admin and pass in dude one two three and it seems that that didn't work let's check the console and we get a server responded with the status of 400 a bad request and if we take a look at the server here it's not giving us any information it's just saying that the post to this URL wasn't successful it was a bad request and the reason for this is purely because we haven't set up rest auth to understand our new custom user because the custom user is trying to see the default Django user that it's used to but we're not using the default user we're using our own custom user so we need to go into our base type I I mean we need to configure the rest or serializers and the rest or three just of serializers and you can check this in their documentation if you just search for custom Django rest or then here the first link is a configuration for Django rest or zero point nine point three so if we check that out in here you can see it says you can define your custom serializers for each end point without overwriting urls and views by adding rest or serializers dictionary in your Django settings possible key values are the login serializer that token serializer the user details serializer and all these so for example it says the rest auth serializers is a dictionary where the login serializer is a path to a custom login serializer and the same thing for the token serializer and it also says you you can define your custom serializers for registration however note the custom register serializer must define a define save method that returns a user model instance and that's extremely important if we want to get this right so first let's copy this default configuration there come back into base add it there and we don't need the token sterilizer we just need the user details serializer that's basically to tell rest off that this is the user model that we're using and that is the specific serializer for that model so we'll copy that user details serializer let's copy that paste that there and obviously the path will sort out in a second and we can also specify the rest or register serializers which is also important because we're going to need to handle the kind of registration for our custom user meaning when the user signs up they need to say whether they're a student or a teacher which means that our registration process is going to be different as well so we'll open up a dictionary here and in here we need to specify the register serializer so we'll add it there and we'll just leave this blank for now and what we need to do is go back to our users app and actually add a serializer inside it so we'll just say new file which will be serializers dot pi how I got this to work is purely just by googling what is required and and so this is primarily focusing on showing you how it comes to work but the model of the story is that when you don't understand something and you're trying to figure out what to do google it and keep looking for examples of where other people have done it and try to apply that to what you're doing now the first serializer that we're going to create is the user serializer and this is the one that we've defined here for the user details serializer so we're going to specify the path here to be users dot serializers dot user serializer and we'll take that name come back into our serializers and we'll just say class user serializer that inherits from the serializers and we need to import that so say from rest framework import serializers and we're going to inherit the model serializer and if we need to use that we're going to need our model so we'll say from dot models import user and here we'll specify the class Mehta and say the model is a user and then we'll need to specify the fields and the fields is just a list of fields on our model that we want to include in the serializer now normally you would have things like the email you would have the username and in our case we're going to also need to pass in the extra fields that we created so we'll add in password as well and we're going to add in our is student and our is teacher and that's it that's our custom user serializer that rest auth now we'll use when serializing our user and now we need to handle the register serializer so we'll do the same kind of concept we'll say class custom register serializer just so that we don't have a really long name and this is going to inherit from the register serializer and we can see here in the register serialize of class it's from rest or third registration dot views register view and then rest all the registration serializers dot register serializer now you can either create your own custom serializer and handle it as well or you can inherit from this rest register serializer and do it that way so that's how I decided to do it so we're going to need to import that so we'll just come back in here and we'll go to the top and say from rest auth and we can actually remove that so we're saying from rest or registration serializers import the register serializer and we'll install these of course now that we have those installed we've got our register serializer and we're going to inherit that in our custom register serializer and this is very similar to a model serializer we can all specify a class meta and the fields so I'm going to do that as well or copy all of that right there however I'm going to add two fields here as well so the first one will be the is student and the second one will be the is teacher and this will just inherit from the serializers boolean field and that'll also be for the each student and now let's actually jump into the front end a little bit to handle that form so I'm actually going to close the models and we'll go into the source to our containers and let's go to the sign-up so here we have signup jeaious and we've got our registration form and basically what we want to do is just come all the way down here to the end of the form where we have the submit button and we want to add another form item inside here which is basically going to be a select field with two options the first option will be student and the second one will be teacher so we'll add a form item and I'm actually just going to copy the get field decorator and just paste it in there and inside here we'll want to add our select so we'll just say select like that and we need to go to the top and import this from and D and we'll specify the get field decorator to be user type so that's how we're going to access it from the forms values and we'll say please select a user and we'll get rid of the validator here as well and inside the select we need to add an option and inside there will be student and the second one will be teacher we'll set the value of the first one to be student and the value of the second one to be teacher and then we can say that the placeholder of the select is select a user type now we need to import option as well so input option there and now we just need to make sure that we handle receiving the value of the option that's currently selected in the form so we'll go up to the top here and we'll say let is student equal to false initially and then we'll just grab the user type from the values because that's how we're doing it currently we have values of username and email etc so we'll say if values dot user type equals to student then we'll say is student equals to true and then here in the on earth where we basically register the user will add another field here which will be is student and this will get passed into the on auth dispatch method so if we go to the bottom here we have on earth and we just need to make sure we pass that in as a fifth argument so this will be is student and that gets passed into the earth sign up which is inside our actions and we'll add it as another argument there as well just like that and now we just need to make sure that we handle that in the store so if you go to store actions auth then here if we scroll down to the auth sign up we need to make sure that we grab that argument coming in which is the is student so like that and what I'm actually going to do is create a constant user and this user is going to have the username the email the password one password two and it's going to have is student which is coming through as an argument day and I'm also going to set the is teacher to be the opposite of his student so that means the student is true then teacher is false then here when we post to the registration URL we can instead of passing this user that only has an email password one and pass or two we're going to pass the entire object that we just created up here which is the user object so we can delete all of that and just pass in user as the object and what we're going to do is actually change the local store handling so that instead of setting the item of a token and an expiration date we're rather just going to set an entire user which will hold the token username and all the details about that user so that way we can store whether they're a student or a teacher as well so what I'm going to do is actually get rid of these local storage commands here but before we do that we'll create another constant here which will be our user and this is going to be the user object that we store in the local storage so it's going to have the token which will be the response data key and just need to reference it with a colon we're then also going to pass in the user name which will be basically the user name that we passed in to the dispatch method so we don't need to pass a code on there we'll then also going to pass in is student and we'll pass in is teacher as well and then we'll set the expiration date here to be a new date just like how we created it over here and just use a colon as well and there we have our user so we can get rid of these commands here and then we'll say set the item of user to be JSON dot stringify the user and we can get rid of the expiration date call there and instead of calling all successive a token we'll pass in a user instead and handle that in a second but basically now we're storing this entire user in the local storage which will come in handy later on as well and so let's go to the auth success method here which is all the way up top here and we'll change it to receive a user instead of a token and then that user will pass in as the argument here and we can remove that there and then we just need to handle that in the reducer so we'll open up the reducers auth we'll go to the auth success and we will actually need to add some new status so for example the user name will now be null as well we'll have is student which will be null and we'll have is teacher which will be null as well and then we can come down here to the old success and and instead of this coming from action token this will be action dot user token we'll take the user name which will be action dot user username will have is student which will be action dot user dot is student and the same kind of concept for is teacher and we just need to make sure that in the action when calling all success we make sure that for example here in the old Czech State method that when we call all the success we pass in a user and not a token so instead up top here we'll say constant user equals to get item user and we're going to need to pass that source adjacent pass the local storage user and that's because this is an object so we need to pass that into an object and then we'll say if the user is undefined all the user is null then dispatch logout otherwise we'll create an expiration date where instead of grabbing this from the local storage this will now come from user dot expiration date where users what we just grabbed over here and we're saying if the expression that is less than new date then logout otherwise we will dispatch all success which will take in the user and we'll just save that and if we go to the logout method as well then instead of removing the expiration and token we can just say remove user we can also open up the terminal to run the front end so let's just clear some of these terminals out here and we've got the package is installed so say npm start so we'll take a look here and it says in actions all we have is teachers undefined and that we just need to set to the opposite of is student and it says that the sign of jeaious doesn't contain an export named options so let's go to sign up and this is because our option inherits from the select so we just need to say constant option equals to select dot option now if we check it out now we can login let's click login and click on sign up and we have a user name email password password and if we click select the user type and when we click the drop down here we see student and teacher as the options for the user type and let's inspect this here and let's see what happens if we try sign up so we'll pass in a username pass in an email and a password and we'll pass in a select use the type of let's say student and if I click sign up we see that gave us a error connection refused and let's take a look as to why that is and it says in serializers get the register serializer yet got not enough values to unpack expected to but got one now this is because of a very silly error which is that we didn't actually add a comma here at the end all and even pass in our path to the register serializer so let's add this Parthia in our serializers and this is users serializers dot custom register serializer just like that now let's come back and try login or signup brother again and if i click student and click sign up now we get a 500 internal server error so let's go back and see and it says your integrity error not null constraint failed users dot user dot is student so basically what this is telling us is that when the user's being created it's not being passed in the is student and the is teacher as well now the reason for that is because the default save method to actually save a user does not involve using the is student or there is teacher fields so what we need to do is override the save method so what I'm going to do is just define the save method here and we're going to say itself and request and all I'm going to do here is just say print the request so we actually see it come through and so with that let's open up the terminal again and we'll go to the signup page but let's actually get rid of the re-routing yes so if we go to the handle submit will not push ourselves to this URL so that way we can continuously test this and from this point here overriding the save method involves using an adapter which comes from Django's all off so if we search for adapter Django all off and we can just click on this first one here then here talks about the advanced usage of creating custom user models and basically creating and populating user instances and here it says all off account adapter default account adapter that is what's used to create an instance of a user and we can actually navigate to Django's rest or and if we go to the introduction let's go to edit on github and we'll just go to Django restore and if we click on rest auth and then we can click on registration and then serializers dot pi and here you can see it has an import from all off that account that adapter import the get adapter and if you scroll down you'll see the different types of serializers so they've got the social account the social login and if we keep going we see we eventually come across the register serializer and you can see all of the fields on it you can see the user name the email password one and two and then these validation methods the get clean data and the save method and here you can see it's saying adapter equals to get adapter and then it uses that adapter from Django Olaf to create a new user using the request then uses the adapter to save the user by passing in the request and the user and then it just add some extra custom stuff here for the custom signup and setting up the user email so what I'm going to do is copy all of that the save method plus the define get clean data and we'll come back in here override the save method and we're going to need to import the adapter so let's go all the way the top year of the file and we'll say from all of that account that adapter import the get adapter and we're basically going to use their logic we're going to get the adapter we're then going to use that to create a new user with the request we'll assign the the cleaned data to self by calling the get cleaned data and what that does is called the method on this class which grabs the validated data and grabs the user name and all these fields from that then using the clean data it saves the user by passing in that new user and we can then get rid of the custom signup and the set up user email and essentially what we want to do is not only grab a username password one and email well actually want to copy password 1 so we have password to that we can see as well and we actually also want to get to other fields which are the is student and the is teacher so now when we call get clean data we're going to get everything that we need to create our own custom user within assigning it to self doc clean data and before we go ahead and save the user we then need to just assign the is student field and the is teacher field to our user so we'll say user dot is student equals to self dot clean data is student and do the same thing for is teacher and then at the end of that we can call user dot save and this is very important this command yeah user dot save so now we then use the adapter to save the user and return that user at the end that's also very important whenever you override the save method you need to return an instance of whatever you're saving so we return the user and now let's actually see how this works out we'll open up the terminal and we see we get one area here which is just the commas so let's add some commas there and now everything's working so if we come back to the boilerplate and this is actually on the localhost let's go to port 3000 and click sign up and look at that it was a successful post request and we got a status of 201 which means that our user was created and if you come back here you can see that it's now saying logout which means that our users actually logged in and that means we can actually go and login to our admin so if we go to admin we're not going to be able to actually log in with our super user that we created earlier and so let's rather just go ahead and use the user that we just created now and create them as a super user so we'll go back in here and actually add a new terminal and we'll say Python managed our pie shell will say from users table models import user will say Matt equals to users that objects get username equal to Matt and let's just change that that's meant to be a user and if we check what Matt looks like there it is and if I say Matt dot is super user equals true and Matt dot is staff equal true and then save we can then exit and if we come back let's refresh this and we can sign in with Matt and there we go we're now logged in and we can actually add our custom user into the admin so let's do that so we'll just go here to admin and we'll say from dot models import user and then say admin dot site dot register user and we'll also want to unregister this groups here so we'll say from janga dot Concha both the models import the group and then we'll say admin dot site dot unregister group now let's come back and refresh this and then we have our users at the bottom and if we click on it we have Matt and if we go all the way down you can see that we have our is student and is teacher fields where is T student is set to true and so let's actually create one more user here will log out and just refresh this and say username equals to test test app Gmail and we'll set the user type to be a teacher and if we click sign up we're now logged in let's go here go back to users we have tests scroll all the way down and teacher is set to true and that basically confirms that our signup is correctly working we've got a custom user that is able to be successfully created on our front end and in the backend and so now what we want to do is actually confirm that logging in works so let's log out here and we're here on the login page and let's try and login with let's say Matt for example and if I click login then we get success as well so in the last one we finished working on logging in and creating our own custom user in the front-end and customizing our serializer with Django's rest auth package to handle that in the backend and in this one we're just going to finish off the user by adding in a view set to allow us to actually view all our users and also to view each user's profile and while we're at it we'll work on creating the assignment serializer as well which will allow us to create assignments so if you'd like to follow along with this tutorial you can just go to github and navigate to our teach me django repository so here it is teach me django and then you can just follow to these commits here to see which commits you'd like to continue from we'll also add a description of these commits inside the project readme file to help point out which commits where the starting code for each tutorial and so once you've got all the code set up and you're ready to go then let's get started [Music] so let's head into the users app and we're going to go to the admin now while I want to work in the admin is because we're going to customize the way that the admin works in terms of these users and how they display everything on this form now we can actually override this entire form we can change it to be our own custom form and that's what we're going to do so what we need to do is first import the user admin which comes from the admin module so we'll say from Django doc contrib dot admin import the user admin and going to say as the base user admin so that we can inherit from this and here we'll say class user admin inherits from the base user admin and then we'll register that with our custom user and recently we posted a video on how to actually customize and improve your Django admin so I advise watching that video before actually continuing with this because in that video we explain everything that we're about to do right now so instead I'm actually just going to go through this rather quickly so we'll add the add field sets and this is basically just a tuple and the first one I'm going to say the name is none and then we'll set up the fields to be email username we'll add is student is teacher and we'll add the password one and we'll add password to and this is basically the fields that are going to display on the add user form well then add the second one here which will be the permissions so that's the name of what we're adding and then the fields are going to be is super user is staff and then we'll add the field sets and this is also going to be a list of tuples I'm gonna copy this first one here however instead of it being password one and two in this case it's just password because now this is the display of the user once it's actually created and then we'll also add the permissions here and I'm also going to add some other options such as the list display and the the list display is going to take in the email it's going to take in the user name it's going to take in is a student and is teacher and then I'm also going to add the search field and this is a list of fields that we can search by so I'll just add email and username and then we'll just say ordering equals to email and if we check the server then we see we're getting this import error and that's because this comes from auth admin so now that's working and if we come back in here and we refresh this page now you can see it looks a little bit different because we're only showing the fields that we want to show and of course you could leave it as the default view but I think this looks a little bit cleaner and you could also go back to users here and you can see the list display is a lot nicer we've got his student and his teacher showing you've got a filter here you've got a search bar and let's add our admins email here we'll just say for example admin at gmail.com and if we click to add a user then you can see all the fields that are required for adding a user which is very convenient as well and so now let's just go ahead and create an API for our user model so that we can fetch users and that'll be useful so that we can come in here and add a profile link and then that would take you to for example slash profile slash one to actually see the profile of that user and we're going to show in that profile are the graded assignments so let's go here to the views and we'll first import our user so you have to say from dart models import user and then we're also going to need our serializers so we'll just say from dot serializers import the user serializer and we'll make this a view set so that it's not a lot of code so I'll say from rest framework import view sets and then we'll just create a class a user view set that will inherit from the view sets model view set and all we need to do there is specify the serializer class which is our user serializer and specify the query set which will just be user objects all and then we can take the user view set and use that inside our own urls da so we'll create one inside the user's model so we'll create one inside the users app and so here we'll just say from rest framework Reuters import the default Rueter and then we'll say from that views import our view set and we'll say our ruta equals to the default Reuter and then we'll say rooted register the regular expression with an empty string like this and we'll say this is the user view set and I'll say the base name equals to users and then set our URL patterns which is what Django looks for equal to the root or URLs then we can just go into our home directory into the URLs our pie and then in here we'll just add a path to the users path so we'll say path users and say include users dot URLs and now if we also just make sure we add a comma there now we can see we're not getting any errors and we should be able to also check this out in our localhost so if we go to slash users then we can see we get the Bolton Django rest framework displaying the user list and if we went to for example users one and put a slash on the end of as well then we get the instance of this user so now what we want to do is translate that into the equivalent display of a user's profile here in the front end and so let's go and close all of this out here and basically where we want to work is inside the source and we'll get started by adding a new root here and this root is going to go to slash profile and then have an ID at the end of that and we're going to create a component to called profile to handle that and we'll just say import profile from containers slash profile and then that means the inside containers we need to create the profile dot J's and we'll get started by creating a class called profile which extends from react and this time we'll use a pure component and we'll say render and then return some JSX and we'll need to import react for this so say import react from react and at the end of this year we'll then create our map dispatch to props and map state to props which will connect to the component so we'll say import from react redux and this is connect and he will say constant map state two props which takes in the state and returns an object and will first grab this token which comes from state author token will grab the user name which comes from state auth dot user name and then will start the map dispatch to prop so it will say map dispatch to props which takes an eight dispatch and returns an object and here we basically want to list out the dispatch methods to actually receive the user's graded assignments however we don't have that functionality yet so we'll just add a comment there and only work with us once we actually have it and then we'll just say export default connect and we'll pass in the map state to props and pass in the profile and if we take a look at this we basically just need to fill in some content here in the return statement so we'll just add a div and say hi and then just say this dot props username and if we take a look at this let's first log in and let's go to slash profile slash one and if we try / - and we don't get the username showing now the reason why we're not actually getting the username showing is because our login method did not save the user into the local storage we still need to configure that so let's head back here and what we want to do is go to the store and to our actions of Earth and here with the auth login method we basically just want to kind of do the same thing as what we did here where we created a user and then store that user in the local storage so we'll just copy that and we'll do that right after we get a response where the token is the response data ducky the username is the username the is student is going to come from the dart as well so i say response table data dot user type dot is student and then will pass the same thing for is teacher and the expiration date is the same as well and then we just want to get rid of these constants here and set the user to a json stringify of the user object and then say or success of that user and so now if we go and try that again and we get a bad request here on the server so let's see why that's happening if we go here to the python 3.6 it just gives us a bad request it doesn't actually tell us anything about it and so basically what we want to do is go back to our serializers and actually configure how we receive a token from the server so let's head back to the users app and if we go to serializers now the reason for this custom serializers so that when we login we receive not only the key from django resteth meaning the token but we also want to actually get the user type and that being either a student or a teacher and we also want to get the user ID and the reason for that is so that we can store that idea now user object and only navigate to our profile and so basically what this means is that we're going to override the token serializer that Django rest all the users so we can just say class token serializer and again you can find this in their documentation as we showed last time and this is going to just be a normal model serializer and I'm going to set the user type to be a serializer method field so serializer method field now a serializer method field allows you to specify a method on the serializer that will return the data that you're looking for so in our case all we need to do is say define get and then underscore the name of the field you created so in our case get user type and it's going to take himself and an object and I'll say that the serialized data equals two now in this case this is going to be the user serializer because we want to get information regarding the user and then return that information and that being the user type so what we pass into it we pass in the object ID user so this is the instance that we pass into the serializer and then we just say dot data so basically we're getting the equivalent JSON object of that data and then we can just say is student equals to the serializer data that get is student and the same thing for is teacher and then we just have to return a dictionary with the keys and values corresponding to what we want so in our case we want the is student to be a student and we want is teacher to be is teacher so this get user type is going to return this dictionary on our serializer and now all we need to do is just specify the fields of our token serializer so we'll say class meta and we'll set the model equals to a token which will import in a second and then we'll say that the fields are the key the user and then our user type that we specified right there and so now we just need to go and import this token which comes from Django's rest framework so we'll say from rest framework dot auth token dot models import token and we can check the server and it's still running and now let's actually bring this to the left here and inside our birthday s we'll just come here and say console dot log the response data and we'll come back here and we'll login and say login with let's say Matt for example and you can see that currently we are only getting the key but now we want to get all those extra fields so we just need to bring our token serializer and take this into our home settings base type I and then here in our wrist or serializers we're just going to add the token serializer and this is going to come from users dot serializers dot token serializer and now let's try it again we'll go login and you can see that currently the error was cannot read property is student of undefined and that's because here in our earth we're reading it from user type which is something that's going to come back here as the user type field on the token serializer so now let's go and login with Matt and now you can see that we get the key we get the user which is the user ID and we get the user type which is specifying is student to be true and is teacher to be false and now you can see that we logged in as well and if i refresh the page we're still logged in which means that we are storing our object correctly in the local storage and now that's just going to add a link here which will take us to our profile so we'll just come back here and we can close our serializer and base up pi and we want to go into the layout so we'll go to containers layout and we already have connected imported which will allow us to access these map dispatch and map state to props from react redux and basically what we want to do is just add another breadcrumb item so we can actually remove the list item here and we'll just make this profile and this is just going to take us to profiles and then an ID so we'll make this output dynamically and use string substitution and this will be this stop props dot user ID then the user ID we can just define in a constant of map state two props which takes in the state and then just returns an object we will say the user ID equals two states auth dot user ID and then that means that we need to store that inside our earth j/s Redux reducer so one we need to make sure that we get it on the login method and the sign up method so we'll come here and say that the user ID equals to the response tab data user remember when we saw that when we logged out the user response in the console and we'll just copy that and go down into the old sign up and also pass it here in this object user so that in both instances we will grab the user ID and that means that inside our reducer we'll need to pass in user ID as the action dot user dot user ID and install this in the state as well and we'll initialize it as null and now that means that we just need to log out and just to refresh this and if we login with let's say mat and if we click on profile currently it takes us to profiles and slash undefined and so if we see why that is we can close this reducer and that's because we didn't put map state two props in our connect method like that so let's come back here and we'll just go back to home and if we click profile now it takes us to slash profiles / 2 and so that ends this tutorial basically just confirming that our users are able to actually log in and we're able to store the user ID and the type of user that they are inside our local storage which will allow us to actually do some interesting things in terms of displaying certain links for example if they are a teacher then you could add a create link here to display which will allow them to create assignments and so we'll get started with that in the next one so we're going to do in this one is we're going to start with the assignments and so this is basically going to be like our API where users will be able to create assignments and those users will have to be teachers they'll create the assignments and then we can see them here in the home view which will list all those assignments out so if you'd like to follow along with this tutorial you can just go to github and navigate to our teach me django repository so here it is teach me django and then you can just follow to these commits here to see which commit you'd like to continue from we'll also add a description of these commits inside the project readme file to help point out which commits where the starting code for each tutorial and so once you've got all the code set up and you're ready to go then let's get started [Music] so let's head over here and I'm going to stop the server and just call Python managers up I start SAP and we'll call it API and inside API we can go to the models to get started with this and so we're going to create three models we're going to create an assignment and so now let's think about the kinds of models that we're going to create we've already mentioned that we're going to create an assignment so let's just add assignment here and if we think about the fields on an assignment we could give it a title and this would just be like the title of the assignment so like midterm exam or something like that and then there would have to be a teacher that's assigned to that title because that's the person that actually created the assignment and we would also have to reference the questions on each assignment I'm not going to do it as a many-to-many field of questions on the assignment instead what I'm going to do is create a question model and each question is going to have its question which will be kind of like the title of the question there will then be choices so these will be the actual answer choices to the question and then we'll also have to assign which of those is the actual answer and we could do this in quite a number of ways we could just make it a character field or we could make it a select field where the choices are equal to the choices of the question but I think the character field is just the simplest way to do it and then we also have the assignment and this is the assignment object that we created here so this will be a foreign key and this will allow us to then assign the question to each assignment we'll then also give each question and order and this is so that we can actually order them on the assignment and the reason why we're creating that instead of using the ID is because if you use the question ID we could have for example question 12 and 13 on assignment 2 and we want to reference those questions in terms of their ID relevant to the assignment so meaning question 12 would actually be question 1 on on assignment 2 or whichever assignment it is so that way by creating an order which would just be an integer field we can assign the order of each question on the assignment and then lastly we have these choices here and what I'm going to do is actually make this a many-to-many filled with a choice object and this will actually also be the answer field as well where this will be a foreign key and in the choice model with simply just going to have the title so basically this just means that will create a choice and then assign those choices to each question and so those are the basic models and what we're also going to create is a graded assignment now the graded assignment is kind of like an in-between model between the assignment and the student and the reason for this is we could just add a field here which would be like graded and this could be like a boolean field so basically meaning that we set it to false when it's initially created and then we set it to true when it's been graded but I think a better approach to this would be creating a graded assignment model so we say graded assignment and these fields are simply just going to be the student who actually completed the assignment we're then going to have the assignment that was completed so a foreign key on that assignment and then we'll have the grade and so that way when a user actually completes the assignment it will create a completely new instance that relates entirely just to the fact that it was graded and I think that's a much better way of managing it let's create these models we'll get started with the assignment so we'll say a class assignment and it comes from models dub model will say that the title is a character field and we'll just set the max length to be 50 and we'll say that the teacher is a foreign key on the user model and that means we need to import the user so we'll say from the users our models import user and then we just need to specify the on delete which will be models cascade and then we'll just define the string method here and say this is self and then just say returns self that title and we can delete those notes there then we have the graded assignment so we'll say class graded assignment which comes from model stop model we'll say that the student is a foreign key on the user as well and we'll also say on delete equals two models cascade will say that the assignment equals to a foreign key with the assignment and will say undelete equals two models dot set null and we'll say that blank and null are true and the reason for that is just because if the assignment was deleted maybe you actually do want to keep record of previous assignments that were completed so that way you can just say set null and basically the assignment will just be null and of course you could just make this models cascade if you want to be simple and then we'll have grade equals two models float filled so that we can handle decimals and then we'll just say define string which takes itself and we'll just say return the self dot student died username so that's the graded assignment we then have the question and the choice and I'm actually gonna bring the choice above here so that we can reference it in side the question model so we'll say class choice from models that model and we'll just give it a title which is a character field and just say the maximum length equals 250 and then define string just like this one and then we have the question model so we'll say class question comes from model step model will then say that the question equals two models dot character field and this could be like max length of 200 remember this is the actual question that they're asking then you have the choices and this is going to be a mini to mini field with the choice model and we just created up here will then have the answer which is going to be a foreign key with the choice and we'll say that on delete equals two models dot cascade and we're going to have to pass in the related name because we're referencing the choice twice so we'll say that the related name is the answer will then say that the assignment that this question belongs to is a foreign key to the assignment model and we'll set undelete equal to models cascade will then create the order which is an integer field and actually we could make that a small integer field because it's not going to get too large and then we can add the define string method and we'll just say return self dot question and there we go so I can delete that and now we have our models assignment graded assignment choice and question and we can go ahead and make those migrations after we add the API into our installed apps so we'll just add it here and there we go so we'll just bring up the terminal here and we'll say manage stop I make migrations and there we have the models created and now we can say and it stopped I migrated there we go and let's run the server now and I'm just gonna bring that down and now inside the API what I'm going to do is create two folders the one folder is going to handle the URLs for the assignment view set and then the second folder is going to handle the URLs for the graded assignment view set so we'll just create assignments and then we'll also create the graded assignments and then inside each one we'll just create a URL stop I and there we go and so now we can go to our home and we'll go to the URLs here and then we'll add a path and we'll say path to assignments which will be the API URL to the assignments views it and we'll just say include API assignments dot URLs and we'll do the same sort of thing for graded assignments like that and this will be API dot graded assignments URLs and we can close that and actually come inside these URLs here and what we want to do is actually the same thing as what we did in the user's app so let's go back to users and down to URLs and I'm just going to copy all of that and we'll go all the way back into the assignments URLs so we're importing the route oh the default router and then we're going to import the view set so we don't have that we create the default tutor and then we register it using that view set which again we haven't created yet and then we assign it to those URLs so we have all of that and we can do the same thing for the graded assignment URLs and so we don't need to focus on the graded assignments for now but it's just so that we can get that set up for the time being and we can then work inside the assignments URLs so we're going to need to work on the assignment view set now so let's go here into the API views and we're just going to create a class assignment view set and actually we can use the same thing as what we did in the users model so let's actually copy everything here and then we'll paste this there and we don't need to render shortcut and in this case we're importing the assignment model and we're going to need to create a serializer file with an assignment serializer so let's do that so just create serializers dot pi just for the time being and then we'll call this the assignment view set which uses the assignment serializer and the query set is the assignment objects level and now we can just handle the serializer so we'll need to import the rest framework serializers so we'll say from rest framework import the serializers and then we'll create a class assignment serializer which inherits from serializers dot model serializer and that means that we'd need our model as well so there's that and then here we can just specify the class matter where the model is the assignment and then the fields will just say equals to double underscore all so basically just pass in all the fields of the assignment and everything is working so let's go actually to the localhost to slash assignments and we see that we get the default Django rest framework list view and let's head into the admin and we can actually add those models into the admin as well so we'll say from table models import the choice question assignment and created assignment and then we'll just say admin dot site dot register each of these and there we go now let's come back and refresh this there we go let's go to the assignments and let's just create one here we'll say the assignment is a test assignment and the teacher is that same admin we'll click Save and if we come back here and refresh this then we aren't getting a come through just yet and actually in the URLs is where we needed to bring in our view set so we've got the assignment view set now and we can put that in our Reuter and the base name is assignments and we're actually getting an area here saying there's no module named API assignments views and that's actually because this comes from API dot views so if we come back and reload this now we can see our assignments being loaded there cool so now we can go to the front-end and actually pull those assignments into a list view to display here so let's just close all of this stuff for the time being and we'll go into the front end into source containers and we're going to create our assignment list jeaious and we'll say import react for our react and we're actually going to need to go to and D now so let's go to and D and we want to find the list which is here and the data display and this first one here is good enough so we'll just copy the code and we'll come in here and paste it and we don't need that mounting there and actually all we want is the large size so we'll delete everything else and then we'll just create a class called assignment list which will say extends from react dot P or component and then say R in and return and we're going to return everything here and just paste that in there and then we'll say export the default as the assignment list and then this assignment list we want to bring into our router so let's go to the routes here and we'll say import the assignment list from containers assignment list and we're just going to add another route on the end of this and we can actually just copy one of these and we'll just paste it here and it's not going to go to any specific path except just slash and we can just add the component as the assignment list and if we come back now we can see it displaying there and of course this is dummy data for now so what we want to do is actually get that data and display it here so we're going to use react Redux to handle that for us so let's go into the store into actions and we'll create a new file which we'll call assignments Jas and this is very similar to what we're already doing here with these actions so we're going to basically need everything from there and just paste it so we've got all fail all success and all the start but of course we'll rename those so let's call this first one the get assignment list start and I'll just copy that but there and that will be get assignment list success and get assignment list to fail and we're going to need to go to the action types and add our actions in here so I just added some actions which just say get assignment let's start get assignment this fail and success and using these we can then import them into the assignments and reference them here so we'll say this is get assignment list start and get assignment list success and get assignment list fail and now we just need to add the assignment or assignments rather into the get assignment the success action so we passed those assignments in there and now we need to create our function to actually get those assignments and so we'll just call this the get assignments which we'll have to take in a token to authenticate the user and we'll just return a dispatch and the first dispatch is going to be the get assignment list start which we define up top there and then we'll set the Axios default start headers to have the content type as application and JSON and then we set authorization to be token and then the token that's being passed into the function and then we can say access get and this is going to be HTTP one two seven zero zero one to our localhost and then to port 8000 to the assignments and then we'll just say dot then with the response that we get from the server will say that the assignments equal to response dot data and then we will dispatch the get assignment list success and pass in those assignments and otherwise we'll catch any errors and just say dispatch the get assignment list fail and that's our method action so we basically just need to handle this in the reducer and then add that reducer to the route reducer so let's go to reducers and we'll add assignments jeaious and this is actually going to be similar to the earth so we'll just copy and paste everything in there except now we don't have any of that stuff so we have assignments which will sit as an empty list to get started and if we go back to the actions let's just copy this name so this first one will be get assignment list start and then we'll copy these two as well so we'll copy that and that paste that there and when we get the list success all we're getting are the assignments so this will be assignments is action assignments and everything else is actually good we can delete the author log out and we can delete that case there as well so now the action type is going to be get list start which will be get assignment left start and then the same thing for success and fail so just like that and that actually should do it for the reducer so let's go into our index.js file and here we'll copy this and just say this is the assignment reducer which comes from assignments and we'll say that assignments is the assignment reducer so now we can access the assignments via the assignments with user and we can close that now and close the assignments and action types and now we just need to connect our assignment list to the store which comes from react redux so this is connect we'll come down to the bottom here and say connect the assignment list and let's go and grab those constants like this so we don't have to repeat ourselves and we've got map states of props and map dispatch which we'll pass in here and we'll change those methods of course so we don't need the user ID but we are going to need the token so we can authenticate so this is going to be state auth token and then we're going to need the get assignments which will come from action start get assignments so let's go and say import star as actions from and then go all the way back to the store to actions assignments and we'll say actions dot get assignments and this is going to take in a token which we pass in there and we can get rid of the dotted list there now and instead what I'm actually going to do is pass in the assignments here which will come from state dot assignments dot assignments and then this is what the data will be as the data source so that this will be the star props dot assignments and if we come back now you just have no data and I'm going to get rid of the header and footer and there we go so that's what it looks like so far and we can said that this is the assignment list and we can actually pass in the loading which will be a state dot assignments dot loading and what I'm going to do is use the skeleton from Andy which is all the way down here to feedback so if you click on skeleton basically it just gives you like a loading screen that isn't just a spinner it's like as if the data is there it's just not showing you it so this is simply just importing skeleton from empty so simple enough just import it there and we can import our higher-order component so we'll say import hoc from hoc hoc and here inside the return statement we're going to say if this dot props then we're going to return the skeleton and say active and then otherwise we will return the div with the data source and the reason why it's not correct right now is because we can't return a dynamic output we have to wrap this with some within something so when you're going to return it inside an hoc so that we don't create a div unnecessarily and there we go now if we come back obviously it's still going to say no data but it's working we just now need to say when we have the token send a request to get the data and so we'll add a method here this one will be the component did mount and basically we'll just say if the stop prop star token is not undefined and it's also not null then we are going to call the star props dot get assignments and pass in the star pop star token and with the same kind of concept we'll do that in the component will receive props this isn't the best method to use right now because it is going to be removed but we're not too worried about that for now so basically we're just going to say if the new prop star token is not equal to the current token then we will say the same thing as what we did here and instead of passing the star pop star token this is the new pop star token and we can actually change that as well so that it's new prop star token is not undefined and new pop star token is not null now if we come back we get new props is undefined so it's added there we're not getting any data come through so let's login now so that's actually going login and I'll inspect this here so we'll login with Matt and let's see we get an error here it says objects are not valid which is basically happening inside the assignment list it says line 34 and that's because we're rendering out just the item so basically it is rendering out an object and to think ahead what we also will need to do is create a detail view for the assignment so what I'm going to do is create a method here that will return each list item but with an avalanche inside it so this will just be render item and it will take an item and we'll just say return this here but we'll import the nav link so we'll say import from react rooted um which is nav linked and we will put that inside like that and this is the link component so there you got the link and we're just going to wrap the link around our list item and here we'll specify the to property to just be like for example assignments one just for now and here instead of being item this will be item dot title because remember each assignment has a title and the teacher so in our case we want to display it using the title and if we come back now we just need to use the render item method by calling this render item of item and there we go you can see that the loading skeleton displayed for a little bit and now we have the assignment list where we also have this test assignment which is the first assignment here cool so the assignment list is working and now we can get the assignment detail working so like if I click on assignment one then you see it takes us to this link here so we basically want to add a route to handle that so let's go back here to route and we're going to just copy that one and say this is the assignment detail which will create in a second and basically we're just gonna copy this here and say when you go to assignments and then an ID then it's going to take you to the assignment detail and now we can come back into the containers and we'll add assignment detail DOJ's and basically what we want to do in here is just create a card so if we check out the cards here from ND which are here under the data display and we can just come down a little bit and see this one here which has an inner card that's quite nice so i'm going to copy that code and we'll say import react from react paste that there and so we have a card which has some inner card stuff and you can actually get rid of the second one and I think we will also get rid of the group title so that we basically have a card and an inner card and then we'll just say class assignment detail extends the react component and we'll say render which will return all of this stuff here and then we can say export the default to be assignment detail and if we come back in here now you can see you get this card with an inner card displaying and basically what we can do is change the card title to be the title of the assignment and then for each question we could add a card here or we could be a little bit more fancy and use some other components from Andy to create this effect of showing one question and then when you answer that question you can go to the next one and etc so that's what we're going to do so we're not going to list through all of them and replicate the card title here so let's just come back in here and we can get rid of the extra there as well and so we basically want to go back to the store and inside our assignments actions and reducers we need to handle getting an assignment detail so what I'm actually just going to do is copy all of this here and we're going to now handle the methods to get the assignment detail so let's go up here and this one will be get assignment details start this will get assignment details success and detail fail and then this will be get assignments detail and in this case we want to you pass in the token and the ID of the assignment that we want to get then we will dispatch the get assignment detail start and get assignment detail success and get assignment detail fail and in this case the assignment is what we will get from the response data and we want to change the get request to be assignments and impasse in the ID and the remember to put a slash at the end of that then the assignment we can pass into the get assignment detail success dispatch and change that as well to be an assignment that's passed in there and we also need to update our action types so you can just do something like this get assignment detail start fail and success same kind of concept as before and then we just need to change this here for these methods so this will be get assignment details start get assignment details success and get assignment detail fail and everything is pretty much good to go so we can actually close that or in fact we can actually copy those methods for the reducer and we actually don't need these to be exported same as the list ones so we'll just grab these three here and then we can come into the store reducers assignment and we'll come down to the bottom and right above the reducer we'll just paste these here and instead we need to basically do exactly what these ones are doing where they're passed in the state so this will be like that and for start we'll set it to this and we can actually come out top here and set the current assignment to be an object which will store the current assignments properties and there and then for getting the detail success then we will pass this or like that and this will be assignment and we'll set the current assignment to be the assignment that's being passed in and then for the fail this will update in the same way and now we just need to add three more cases in here to handle those so we've got get assignment detail start which will get assignment detail start get assignment details success and failure just like that and it's just check is the server happy and it is so now what we need to do is basically just call these methods here inside the assignment detail so we're going to basically do the same thing here we're going to need the connect method and we're going to wrap it around the assignment detail and I'll actually just go to the bottom and copy all of this here and then just rename this to be assign and detail and we'll import just the function we need from the store so this comes from store actions assignments and this is the get assignment detail and that's what we'll plus in there as well and we know that it takes in a token and an ID so we pass the token and the ID in there and instead of having assignments will have the current assignment which is from State assignments and just fix this dispatch there and what we want to do now is the same thing as what we did with component did mount and component will receive props so we'll copy that paste that they accept this will be get assignment detail and we'll put that one there as well and we need to pass in the parameter coming from our URL so that would be the stop props match params dot ID and we can actually just copy that whole line and there we go so if we come back seems like everything's good we'll just come here and instead of the title being card title we'll output this dynamically and say that this is the title which will come here and say constant title equals to the stop props current assignment and if we come back we're getting an unauthorized error and that might be because of our settings so if we go to home settings based up PI and go all the way down here and we can actually change this to be is authenticated and I'll remove the session and basic authentication classes and let's come back and refresh this and let's close that and come back here to the detail view and that's because we're not passing in new props star token so let's get rid of that and try this again and there we go we see the test assignment title coming through there and so now let's go back to Andy and we're going to take a look at the step component now the step you can find here under the navigation and this is basically what it looks like it's just like navigating through some kind of step by step task and the way that we want to display this is kind of similar to this one so we're just going to copy that code and let's actually go into containers and we'll create another one which will be called questions jeaious and this is going to basically render out a step by step display of our questions so let's just paste that all there and we can come to the top and we'll rename this app to be called questions and go to the bottom and say export default questions and we're going to need react so we'll say import react from react and I'm gonna get rid of the constructor and just say this state is like that and we can actually just take these questions and bring this into the assignment detail so let's go over here and we'll say import questions from questions and we'll take that and we will display that inside the inner content like that and let's take a look and this is what it looks like now it's not displaying this thing here because we didn't copy the CSS which looks like that but I don't think we actually want to either but instead what I'll do is if we come back here and go back into questions we'll just go up to the top here and this div will say that these style has a height of 100% but what we'll do is we'll make sure that this content actually does have some padding on it and it'll look better once they actually are questions inside there and we don't want to display these large balls here like first second third etc we're just going to have little dots instead so we can do that if we actually just close that there then you can see it looks like this and the way that you do that is just by putting in progress dot like that and bring it into the steps and if we say that now it looks like that and that looks a little bit better and I think we can actually get rid of the inner cart title as well we can get rid of the whole inner card and just display these steps so let's go back to assignment detail and I'm just gonna cut out that card and place it like that and we can actually import the skeleton as well from an T so bring the skeleton in and we have the loading as well so we'll also bring in our higher-order component like we did here in the assignment list and we'll return the higher-order component and inside it will do the same kind of thing and say if this doc props tarting then we'll return the skeleton and say active and otherwise we will return the card like that cool and save and and actually I'm realizing that we will need the inner card so that we can display the question number so we'll just create that card again and just bring the questions in there you will say type equals to you know and what I'll do is say title equals two and let's just take a look again also we haven't given it a title we could specify the title here but what we want to do now is we want to basically grab the questions off of the assignment so when we grabbed it here from the server we want these questions to be passed into the assignment detail and I think what we'll do is we'll pass them in as props into the question component here and then inside these questions here we'll then loop through them and display however many questions they are so basically the number of dots here will depend on the number of questions that's basically what we're aiming for so let's go back in here and what we'll do is we'll say questions and inside there will say that the questions equal to the current assignment which we've got up here and we can actually just say constant equals to the stop props and then say title equals to current assignment and in like that we can pass that into here and say current assignment dot questions and we actually can just put it like that and what we can actually do is return a card by mapping through the questions we can return a card for each question and pass basically a list of components into the questions and that way when it comes through in the questions here the component that will render will not just be this over here the start in the steps it'll actually be a component and so let's just see how this will be done we'll say dot map and we'll say for each question we're going to return a card and we can actually just cut that out and say that there when we do that we're going to need to specify the key which will be the question ID and the title of the question is going to be the question order and we can actually then put the question next to it so what we'll do is we'll output it in strings and just reference it with substitution so question order dot and then question question and that looks a bit better and now inside the questions component we need to handle that so let's first get rid of the steps we don't need that and the logic here of the current is correct we'll keep that will keep next and previous and render but then here we'll say that the constant questions equal to the stop props because we're going to receive it as props so this will be questions and these questions here will loop through inside the steps so now instead of using the steps that was defined up top there we're now going to use the questions and say dub map for each question and we can also use the index to use it as a key so for each question we're going to create a step where the key is going to be equal to the index so basically the index of the element in the list and we don't need a title either we're basically just creating a step we can remove these class names because you don't actually have the CSS for that and this stuff here is rendering out what used to be steps of the current step but now we want to change steps to be questions so that it will render out the question according to the index of that question within the list of questions we've passed down so we can remove content as well and if we take a look at this we've got steps as undefined in line 33 and we can change that to be questions lengths and questions the length and let's take a look now and we're getting a cannot read property map of undefined and the reason for this is because of our serializer so let's jump back into the back end and go all the way to API and then to serializers now the issue is that we have a nested component questions are referenced by a foreign key in the question model and so that's why we're not seeing it come through and so we're going to actually do the same kind of thing as what we did in the users if we go back to the user serializer we used a serializer method field where we defined the method to actually get the starter or we're going to do the same thing here for our questions so let's just close that and we'll say that the questions equals to serializers dot serializer method field and then here we just add a method and say define get questions and say it takes self and object now in order to get the questions we need to actually use another serializer and that serializer will be the question model serializer and so let's just go here and say class question serializer and nothing funny is going to happen here we'll just say serializers dot model serializer will set the class meta to have a model of question which will import for our models and then we'll just say that fields equal to all like the previous one and this question serializer is going to be used to serialize the question objects and so we can say that the questions equal to question serializer where we're passing in the object remember this object is an assignment so we pass in the assignment but we want to access the questions off of that assignment and we can do that because if we took a look at the models again the assignment doesn't have a questions field on it but if you go back to the question model we specified the question to have an assignment that was a foreign key of the assignment model and basically what we need to do to make this work really simply is just by adding a related name so we'll just add related name and this is going to be questions now when we do that this allows us to come into the serializer and say get object questions dot all even though we don't have the field on the assignment the fact that we have the foreign key with a related name allows us to make that kind of query and we actually need to make a migration for that so we'll say make migrations and then we can say migrate and then we can run the server again and we can close the models and now using the question serializer we're passing in the objects questions by using the related name and we want to set many equal to true and that's basically saying almost like there are going to be many questions that we need to pass because this is a nested serializer and then we'll just say dot data to get the data from the serializer and then just say return the questions and so now if we take a look at this and refresh it we're still getting undefined so let's go into the assignments here and we'll just say console dot log the assignment to see what's going on and to basically get around this with a dirty trick what we can do is go into our assignment detail and here right above the higher-order component will just say object keys of the current assignment and say dot length and if it is greater than 0 then we will do all of this here so let's just cut all of that and bring it there otherwise just return null and that means that we also need to wrap all of that inside a higher-order component as well so we'll just cut that out bring that there and now we're basically saying if the current assignment we have from the props has more than one key inside it then return the stuff otherwise return null so now we can see at least that's being displayed and it allows us to actually let the component will receive props take place and then you can see here we're getting a response in the assignments which has an ID of one and we're getting a questions array and you see it each question has an ID and as the question field the order the answer etc and we also get the teacher but it's only returning one so that doesn't help too much and for the choices we also only get one and two so we basically what we want to do is convert any time that we see something that shouldn't be returned as an integer or writable or returned by its ID we want to view it as a string we want to see what what does its define string method because that in that case what it's going to do is for the choices it's going to return the actual text the title of each choice instead and the user will be returned by their username and not by their ID and we can nail that pretty quickly if we just go back to our serializer we can use a string serializer so we can just say class string serializer and say this inherits from sterilizers dot string related field and this requires one method which is the two internal value and it takes in self and a value and then we just say return value then what you can do is you can use the string serializer to convert fields in your other serializers into a string so for example on the question serializer we have these choices that's a field on the question model so we can say choices equal to string serializer where many equals true because there are many choices for each question and then we can return that here inside the fields and if you wanted to return the teachers well let's say you wanted to return the teacher's name and put in the top right hand corner then you could do the same thing and say teacher equals to string serializer where main equals false but we don't have that on the question so we'll just leave it as it is and we'll change the fields to be ID choices question and order and then we can come down to the assignment serializer here and we'll say that the teacher is here because that's where it is and again we'll use the string serializer and pass in many equals to false and cool we'll just leave this as all because we pretty much are returning all the fields so now if we come back here and refresh this now you can see the ID you can see the questions and each question has two choices you can see cool and not cool you can see the question with its title you can see the teacher by its username of admin and that's really convenient so now what we want to do is add the choices for each question inside the question so what we'll do is we'll go back into our source folder and here we're going to create a new folder inside there which is going to be called the components folder and this is going to hold the choices and make sure this is choices j/s because we're basically just going to pass the state down into it we're not going to make this a container and so we'll start by importing react from react and how we want to do this is to use the radio and this is part of forms so if you go up here you can see this vertical drop down of radio options we'll just copy that and we'll change this to be class called choices and then say export default choices and we can get rid of the last radio item and we'll remove the radio style to be outside of the class and let's take this choices component and we'll remove the input there and we're going to take this component into the assignment detail and we'll say import choices from components choices and what we want to do is render the choices inside the card all right that makes sense so we're passing the cards as components into the question but each component card but each card that we pass in has answers inside it so if we go all the way down here to the card we basically want to pass these choices inside it so like that will say choices and we'll just do it like that for now and let's see what this looks like and now you can see get back option ABC for the questions and what we can also do is come up top and just to find some styling which we'll just say is the card style and all we're doing is just making the margin top of 20 pixels and the margin of bottom of 20 pixels as well you can come and bring that card style down inside here so we'll say style equals to card style and let's check this out and now it's a little bit more spaced out and looks a bit better and you can select those different options as well and let's go and actually create another question and we'll add an answer and say let's say it's true and if we refresh this we've got true there we'll say choose the answer and I'll add another choice which is false we'll say this is question to the assignment is test assignment the orders too and if we come back here and refresh this now you can see there's two dots and if you go from next to the next one you're going from question two to question one and back and that's pretty cool so now all we need to do is just pass in the options or that rather the choices of each question as the actual choices to this radio group here and so we already have the choices component that we're passing into the card so inside there we can add some props and say this is equal to the questions choices alright because we're getting the choices off of each question and that way when we go back into choices here we can just come down here and instead of rendering out these components over and over we will output them by mapping through the choices that came through as props so we'll say this table props dot choices dub map and we'll just say for each choice and pass in index we will return a radio item like that and we'll say that the value equals to C where C is the choice that came through and the text that goes inside there is the actual value of C as well and we'll say that the key is equal to the index that was used to loop through in map so now if we come back and so we're getting a warning here which is saying that we're getting a unique key property error and we actually want to remove this value statement there that's coming from the state so what we'll do is remove the state there and what I'm going to do is take the on change and bring this back into the assignment detail we'll put it over here and instead of the value being now coming from the state well how we're going to manage this is pass the question ID into the choices and so that way we can basically store inside the assignment detail the answer to each question inside a dictionary or an object where each key is the question ID and then the value of that question ID is the answer that the users chosen and that's very easy to update in the state so basically what we're doing is at the top here we're just going to say that these state equals to this object that has let's call it user answers which is an object and then in the unchanged we're not only going to take in an event but we're going to take in the question ID that was changed and so we'll grab the users answers via the state and say this equals to the start state and then we'll say user answers of that question ID so we're setting the key in the dictionary equal to the event target value and then we can just say this dot set state of users answers and now we just need to pass the on change inside our choices so what we'll do is we'll say change equals to this dot on change and then we can handle the change property here and say when unchanged takes place then we'll say this takes in an event and a question ID and say it's an anonymous function that calls the stop props dot change where we pass in the event and then we need to pass in the question ID which we'll grab by passing down as well so we'll come into assignment detail and we'll say that the question ID equals to Q dot ID and in that question idea here we can access you in the render so we'll say constant question ID equals to the stock props and then pass in that inside our prop star change and what we can also do is pass in the user's answers so Racha above the return statement will say that the constant user's answers equal to the state and we'll just wrap this 2d structure it and we'll pass that down into the choices as well where it equals to users answers and in fact the question ID should actually be referenced with the order because otherwise we'll get the actual ID of the question which could be like 12 13 14 etc where you only have two questions and it's gonna say question one is number 13 so that doesn't make sense it's actually meant to be the order like how we were displaying it in the title and so what the users answers being passed down into the choices we can now say that the value that's currently selected in the radio group is equal to the value that's in the state so basically what we'll do is say if users answers in which you can actually grab up top here say constant users answers equals to the stock props and say if the users answers are not equal to null and basically just check if the question ID that's coming from the users answers is not undefined and it's also not null so if that's true then we will say that the answer is the the value of the question I'd be inside the users answers and otherwise it is null so basically that's what it looks like and so if we take a look here we'll need to login and if we go to test assignment now you have the first question there and you've got its answers showing you've got cool and not cool and if you go to next you got true and false and now if we select cool and go click Next and go back you can see that that state was preserved meaning the answer that we selected is still there and if you go forward you can click false or whatever go back and forth and there we go so it's preserving the states in the questions and basically what this means is that all we need to do is just add our questions in the back end however many questions you add it doesn't matter because those questions will be looped through to give you the answers to those questions inside each card component and each card component is being passed in inside each question so in the last one we added our assignment list and detailed views to this project and so if you'd like to follow along in this tutorial you can just go to get up to our repositories and you can go to the teach me django repository and then you can just navigate to the commits to see which commits you'd like to navigate to so currently we're on this third commit which is the assignment list and detail views added and so you can just clone this repository and navigate back to those commits and so once you have everything cloned what we're going to do in this tutorial is basically just add the form to create the assignments and also handle the graded assignments so we're going to try and tackle both of those in this video so once you've got everything up and running and let's get started so we have the front end and the back end servers running and we can check this here in our boiler plate and so this is what the assignment looks like you can just select the answers and when you click done then it gives you this processing complete which is basically just a message that displays when you click the done button so you see a get message dot success and so what we want to do is handle the creating of a graded assignment when a user is finished answering all the questions so basically we'll submit the users answers to each question and then on the server we'll evaluate whether the answer they selected was the correct answer and then create a graded assignment object which will hold the grade of that users assignment so we'll get to that in a second but what we actually want to do first is handle the form that will allow us to create assignments and this will only be allowed for users that are teachers so they have that use teacher property being true and so we're just going to come back in here and we can actually close off a lot of this over here and we're going to go inside the containers and create the assignment create jeaious and we'll just copy that name near and let's just import react from react and what we want is actually a form that will allow us to add more fields to it so here and and D we can just go to the form and if you scroll down then we're looking for this one here which shows that you can add a field and you can also remove those fields so we'll just copy all of that code and we'll come back in here and it's actually quite a long one and I'm actually going to remove the comments as well and I'm going to remove these form item layout objects and the labels as well we're not interested in that and so let's just take a look at what this looks like we don't also don't need the react on render and you'll say export default and let's call this the wrapped assignment create and export that is the default and then just make this the assignment create like that and then we'll come into our routes and we're going to import it so we'll say import assignment create from containers slash assignment create and we want to create a new path here which will be when we go to slash create and this will be the assignment create component that will handle it and let's see what errors we get so we get that form item layout problem and we can just sort that out so we can just get rid of that there and all of the form item layout with label rules let's check out now and let's go to slash create then we get this form and we can add fields and remove them as well and so let's add a link here in the breadcrumbs of our layout so that we can navigate there so inside the layout component we can go to the breadcrumbs and we'll add another one here and we already have the user ID in the state and let's actually add the token so this will be state auth token and we're also going to add is teacher which will come from state auth dot is teacher and then with the breadcrumbs what we want to do is actually we don't want to display this link if we aren't authenticated so we'll add a check here and say if this dot props token is not null then we will show that link otherwise just return null and actually we can put that outside the breadcrumb and in the same kind of concept for the next one so we'll just copy this entire thing here and we're saying if the token is not null and the stuff props that is teacher is not false or in other words we could say and the star prop star is teacher so meaning it is true then we will return a link that takes us to slash create and we can actually output that like this and we'll say this is create and there we go now let's come back and if we refresh this and we see a little area let's get rid of that they we have to say and this stuff prop study is teacher and we get profile showing in brackets so let's get rid of those brackets there and there we go okay so let's go into the admin here and we're gonna go change this math user to be a teacher so we'll just select that to be true save and continue come back here refresh it and we'll actually need to log out and login and there we go and just getting those brackets again so let's remove those and there we go and if I click on create and it takes us to that form name and so let's go back in here and we can close the layout and the routes and what we're going to do in the assignment create is we're going to manage the questions themselves so here how we're adding a field this is like going to be adding a question and we're going to manage those questions here on this component and we're going to create another container which will be the question form so basically we're creating like a form set and what we'll do is we'll just render the question form over and over depending on how many questions we want to add and we'll again manage the number of questions here inside the assignment create and then the question form will actually be very similar to what we have here we can actually pretty much copy everything in this file and paste it in the question form and then we'll just rename everything here so this will be wrapped question form and in fact actually we're not even going to create a form using nd because what we're going to do is rather create form items and then pass those form items inside the general form that we have here so inside this form and so instead we can get rid of that call there and we'll just call this the question form and then this is the class question form and so everything here is pretty much going to remain the same we can actually make this a little bit shorter and so each question form will manage the keys of that form whereas the handle submit we're not going to handle on the question form that will rather be on the assignment create view so we can get rid of that and now we have the render method and so the label of this form item will not be the passengers but instead this will be the choices so inside the question form will manage the choices of each question and in the assignment create form if we just scroll up passengers will rather be questioned and so let's actually go into the assignment create and think about the form items that we want to have inside the main form so we're going to have this button which will and asked to add a question so let's rather make this add question and this will be the submit button but instead of making this a dashed we'll make this type secondary and we'll actually get rid of the with style and if we take a look at this now you've got add question and submit there and what we also want is a field to pass in the title of the assignment so we'll just create another form item here and we'll set the label of this format and equal to something like title like that and then we're going to need to use the get field decorator like this one so that we can actually give it a name which will access it by so we just paste everything in there and we'll keep all of those rules there except for whitespace and the message here we can just say is please input a title and then inside here these braces where we actually pass the component to input is going to be an input which we already have over there and we can take a look at this one as an example so we'll just bring that inside there and this input will have a placeholder of add a title and we can get rid of the styling as well so now if we take a look you see K is not defined and that's the gate field decorate a name so we're going to change that to be title and if you come back here now you've got the add a title field and add a question and we'll also add an h1 above here and then they will just say create an assignment and then these form items which we're basically mapping through the keys what we're going to do here is rather just store a count of the number of question forms and then create a question form to pass in based on the number of counts so actually this constant form items will just change two questions and initially this is actually going to be an empty list and we can get rid of everything right here inside this method so everything up till there we can get rid of the keys we can get rid of this get for your decorator there and can get rid of that because we're not using it and then let's just go up here we have the handle submit which will keep us this for now we've got the add method and instead of using this get filled value of keys which doesn't exist anymore we can basically just get rid of all of that we've got the state that we need to define up here so we'll say state equals to this object here which has a form count and you'll say the form count initially is one and we can also remove the ID from up top there and then everything here and the remove we can also get rid of that and we'll just make this an anonymous function as well so inside the add method what we want to do is grab the form count from the state and then set the state to just be that form count plus one so basically that you're just adding one to the form count so we'll say constant form count equals to the start state and then we'll say this set state and pass in the form count to be form count plus one and then the same kind of thing here in the remove method where this will just now be minus one so this is a very basic way of doing it maybe you won't be removing the exact question that you wanted to remove but all the time being it's it's good enough and then we can just come down here and what we want to do is loop through the form count in the state and create ourselves a question form based on the number in the form count so we'll say for let I equals zero and where I smaller than the start state dot form count and then just say I plus equals one then here we will push a component into the questions array and then render those questions here like this and so what we want to push inside here is going to be the question form so let's actually make sure we've imported that so say import question form from question form and then over here we will just push that inside like that and so let's take a look we see we've got get filled decorator of undefined inside question form and that's because we took away the method here to create an ant deform so what we want to do is pass in the props of this component which is being created using the ant deform inside our question form so that it inherits those props so we'll just say pass in the stuff props now if we come back cool now we can see it's kind of taking shape except you've got a submit button there so let's come down here and remove this form item and that's starting to look a little bit better but now we're getting this each child in the array should have a unique key property and so if we come back in here to the assignment create we could say that the key equals to I and if we come back now we're just getting a nesting problem which is basically that we can't return a form itself so we're going to need to remove the form there and these form items we're basically going to need to wrap this inside a higher-order components so let's say import Hoc from hoc and they will take this and just wrap it around everything we have here and so we've got add a field here so let's make this add an answer choice and what we also need to do is specify the actual answer itself so we're going to need to create another form item above it so that the user can specify what the answer is and again you could get creative and maybe add like a checkbox next to each answer choice which if you selected that one would make it the answer but just to get this thing to work let's just copy some of the stuff we have here so we'll just make another form item and then we'll need the get filled decorator as well so let's just copy that and if we just save that so you can see the get filled decorator has the strange syntax of names of Kay and basically what that's doing is allowing each form item to have a unique name that you can grab its value from and so we'll need to play around with that to get this to work so for the timing let's just add a label here and make this answer and we'll say please input and answer to this question and if you come back here we've got K is undefined and that's basically this problem here so for the time being let's just put in answers and if we come back we've got a cannot read property props of undefined and that's because of the answers that we have here now basically what we need to do is ensure that every question form has a unique gate field decorator not only within the form but compared to other question forms because let's say we render out five question forms that all have a gate field decorative answers and it's basically going to set the value of each field in those five questions to be the same thing because it's got the same gate field decorated property so basically what we need to do is pass in the question ID from the assignment create component here and using that that question ID we can then differentiate each question form from the next one so basically here we'll use that same syntax debated where you basically pass in like a square brackets to access the index of to access an element by its index and we'll just say this docprops/custom.xml create it and we'll set ID equal to I because I is just one way of incrementing through it and so if we refresh this we're still getting that error and so let's go back into the question form and we can also remove whitespace from there and we also need to pass in the actual form component Enya which is actually going to be an input so we can just grab this one here and put that in there as well and this is going to be the actual answer to the question well in this case the choices basically so we'll have you the placeholder as what is the answer and we'll remove the style and let's come back and see and there we go now it's working and we've got add a title we've got what is the answer we can add an answer choice and we're still getting those passengers coming through and that's just coming from inside here and so we're going to need to kind of do the same thing with the get filled decorator of the choices so this this is going to be choices here and we'll set the get filled decorator to be choices of the stuff props ID and we'll say please input a choice to the question and then the placeholder here will be the answer choice and then we can get rid of the style there so let's just take a look at what we've got here we've got one form item which is the choices and that's being looped through based on the keys count which is what we had by default from Andy and we're using the ID of each question to differentiate the choices of each form and we can get rid of that required false there we don't need that and each choice that's being looped through has its own input which says answer choice and if the key length is greater than one then it's going to show the icon which will allow you to remove that answer choice then we're returning a bunch of form items the first one is going to be the actual answer to the question so it's going to say what is the answer so he input what the actual answer is then it's going to give you the choices to input and then a button to add another answer so if we take a look at Beth you've got the title the answer add an answer choice and add a question now what we need is a field that says what is the question and so if we come back in here where that can go is actually just right here above the answer for madam so we'll just copy that paste it there and this will be question and then this here the get filled decorate we're going to use as question to differentiate and call this top prop star ID and we'll say please input a question and then here this will be add a question and if we save that and check it out now you've got one form showing which asks you for question the answer to the question and then the choices as answers to that question and if we add a question you can see that the exact same form was repeated you've got add a question what is the answer and the answer choice and you can add an answer choice to each one and so to kind of help differentiate the forms from each other we'll just add a divide between them so let's go back to the answer create and we'll wrap this around with an hoc which will actually need to import so we'll say import a chassis from hoc and then here we will wrap this around like that and then we'll pass in a divide and a divider basically comes from and D which is another one of their components and then we can just simply just add it like this and so now we need to pass the key inside the higher-order component and if we check this out you can just refresh this now you've got that divide there and if I had a question then at least that divide is kind of separating them you could make that thicker as well and so we'll also add a little icon next to the question to remove that question so just like how they do here where they say if Keys dot length is greater than 1 then return an icon like this and we'll grab that there come here and here where they're pushing each high order component we're adding a question form and a divider and so I'll just put it right there and say if questions dot length is greater than 1 then written an icon and we're disabled is where questions dot length equals one and unclick will just say this dot remove like that so let's see what this looks like and if we add a question then we're seeing no icon yet so let's go back here and say yeah if it's greater than zero and disabled as if it's equal to zero and if I click add question then there's little icon to remove that question and that's actually try and add it above the question form and see what this looks like so if I add a question then there's a little icon and if you press it then it removes the question cool so let's actually add that question and let's just pass in a title and just say test we basically just want to see what the data looks like when we submit it and we'll say this is question one say this is answer 1 we'll add an answer choice and make that answer too and the question here will be question 2 the answer will just be answer two and just some choices and we can make that one and okay so we're seeing that this is giving us the same answer inside the choices so let's go back here to the question form and so the problem is basically happening here inside this gate field decorator we're calling choices of this type props that ID but this should actually rather be choices of K like it was and outside here we're going to pass in questions of this type props that ID and so now if we check this out and we'll add an answer choice there then you can see that those values are now different they're unique so let's fill in the rest of the form if we click Submit we've got received values we've got answers are a and B the keys are 1 & 3 because we deleted one of those keys we've got a question which is question 1 in question 2 where those are the names of the questions we have here and then we have the questions arrays which are the array of choices to each question so we've got empty and then a and basically Bieber and then you've got the second one here B and that so that's how the dots is coming through and okay as we also have the title day so we want to basically take that data format a little bit and send that through to the back end where the server will basically create the form and so let's go and add the functionality inside the submit method yeah so here you've got handles submit and so basically the format's of how we want to submit this is going to be an assignment object so we'll say the assignment equals to an object and it's going to have a teacher right because we know when we create an assignment it has to have a teacher and it has to have a title so those are two easy properties that title just simply comes from values title and then the teacher is going to be the star props that username and we should have that at the bottom here so we'll just go and copy that from the assignment detail so let's just grab everything there and paste that so we need the username which is going to be state auth dot username and we'll pass in the wrapped assignment create inside that Connect method there just save that and we're going to need to import connect from react redux and then we'll also add the actions in the store to handle creating the assignment so we'll get to that in a second but let's just get this object sorted in our handle submit so we've got the teacher and we've got the title but we also want to pass in the questions for that assignment and I think the easiest is just to simply add in questions like that and this questions key is going to be a list of question objects and each question object has to have a title it has to have the choices and it has to have the answer so basically we're going to loop through the props in our form push each question that will create as an object into a list of questions which will then be passed here into the assignment object so we'll start with the questions which is going to be an empty list and then we'll say for that I equal to 0 where I is smaller than the values questions dot length so basically the length of questions and then we'll say I plus equals 1 and every time we loop through we're going to say push and we're going to push an object inside there where each question has a title it's going to have the choices and it's going to have the answer and so the title is simply just going to be the value inside the list of the questions so this is just going to be values like questions of I and actually for the time being let's just comment all of that out and this is meant to be a colon there so let's just go down and comment out the get assignment detail and I'll just add some dummy dot here yeah you've got the question which is a list of question titles and then you've got the questions which is a list of the choices to that question so basically what we need to do is make sure that we don't pass in the empty values in those rights you can see you have empty and then on send incorrect you want to get rid of those empty values so what we're going to do is let's just go back up here we're going to set the choices to be values dot questions and actually this first one should be question of Aya's question has an array of question titles they were asking where's questions has a list of objects that have choices inside them so we're going to say questions of I to grab each instance from that list and then we say dot choices to access the choices of that object and then we need to filter that where we don't want any null values so basically we're just saying we're is not equal to null and then the answer is just going to be values dot answers all right and we just need to put a comma at the end of that call so now we've pushed the object into the questions array and we've passed those questions into the assignment and now we just need to create the actions in the store to handle the logic of pushing that to the server so let's go and do that now we're going go into the store here into assignments and all the way at the bottom here we're going to need to actually just basically copy all of this again and change this to be the assignment create logic so this will just call create assignment start and then this one will be create assignment success and create a Sun detail or create assignment fail rather and then this one will be just create assignment when we create the assignment we're going to take in a token to authorize the user and then we're going to pass in the actual assignment when it's created so here in the assignment create this object will pass into this method and will dispatch get or rather create assignment start and then here we don't need to console that art we can just say dispatch create assignment success and create assignment fail and we're going to need to change this to be a post request where we'll post it just to this URL because it does handle post requests and we're not going to get anything back from the response we're just going to basically just dispatch the create a sign of success if it was if it did receive a response and if there was an error then we just dispatch the fail and now we need to go and add those action types in here so something like this create assignment start fail and success and you can take those and bring them into these actions so this will be create assignment start create assignment success and create assignment fail and in the assignment here we need to post as the object that's being posted and that's pretty much it that's the whole method handled so we can bring this here into the assignment create and we'll say import create assignment from the store and then that create assignment we will pass in over here which takes in assignment dispatch that method which takes in that assignment and then we will call here this props dot create assignment of the start prop start token and the assignment so like that and let's see if we've got any errors so we're getting assignment in line 113 so we come here and that's because we don't need to pass that into the create assignment success cool so let's add a title title test question 1 the answer will be yes and the choice will be yes or no and I'll just say submit and of course we get a 500 internal server error because we just aren't handling the creation of these assignments the way that we need to be doing that so we can go and close the assignments there and question form and actually we didn't actually do the reducers yet so let's go inside here so we'll basically just copy all of this stuff here the assignment details start and all the way up to the success and I'll just copy and paste that there and this will be the create assignments thought this will be create assignment success and then create assignment fail and then here we'll add in three more cases the way this one will be create assignments start and we'll say create assignment start and this will be create assignment success which will be create assignments exists and the fail one and let's just go handle what happens there it's pretty much going to be the same thing except we don't get any assignment action there and pretty much that's it there so we can close the reducer and we'll go into our back-end now so let's go to API and we're going to need to go to our views here we have the assignment view set and so basically you can actually override the methods on a view set and you can check that in the documentation of the Django rest framework so for example if you wanted to override the create method you could just say define create which takes in self and a request and the basic logic that proceeds when the create method is executed is that it uses the serialize it so the assignment serializer in this case which is in serialize of pi so it would take the serializer and we would pass in the request data into the serializer then we would say if the serializer is valid then using the serializer creates an assignment because that's what the serializer basically does converts the JSON into an object and then return a response which is either an HTTP 201 that means it's created or returned an HTTP 400 which means it's a bad request so basically we will say that the serializer equals to the assignment serializer this one here and we say that the data equals to the request data which is coming here inside the create method and then we just say if the serialize ODOT is valid then proceed otherwise you can just call it like this you have to do that otherwise it won't let you move on and then we'll just say that the assignment object equals to serializer dot create the request remember this will only happen if it's valid and we can actually just do that if serializer is valid and we'll say if there is an assignment then we will return a response and the response we can import from the rest framework so we just say from rest framework dot response import response and then we'll import some statuses as well we'll say from rest framework that status import and we're going to need the 201 which is created and we're going to need the 400 bad request and then we'll just grab that there and say return response where the status equals to HTTP 201 created otherwise return a response where the status equals to the HTTP 400 bad request and you can put that like that cool so this assignment serializer dot create this is a method on the serializer so if you come here to the Syrian laser we can actually define that create method and that's gonna be quite handy because the data that we're getting in in the serializer is really just not going to match what the serialize is expecting so we're going to override the create method on the serializer to pass all that data into exactly how we need it to be passed and then create the objects that need to need to be created so for example the choices and then assign the choices to the questions assign the questions to the assignment and return the assignment basically that's what we're doing and so it is quite a long method so we'll say define create and it's going to take himself and request and remember this request is what's being passed in here this request there so we get access to the request up data so we'll say request that data equals to that data and we can actually print it out as well so let's test it out we'll add a title will say question one answer is yes choice yes and no click Submit and let's see inside the terminal and here you get the teacher is Matt titled as title questions is a list of objects where we've got title as question one choices is yes or no and the answer is yes cool so with this data we basically just need to think about what we need to create in terms of models so so far we've got the assignment to the question and we need the choice as well and so we'll start by creating the assignment so we'll say the assignment equals to an assignment object like that and we're going to need to assign the teacher and the title to the assignment so we'll say the teacher equals two user objects get where the username equals two data of teacher remember teacher is Matt in this case so we're getting the user object that corresponds to that username and we're going to need user imported so say from user dog models import user and if we come back down here then we can say that the assignment teacher equals to teacher or say the assignment title equals to data of title and then we say assignment dot Save cool so that is the assignment being created now we need to create the questions and the way that we're going to do that is just by looping through this list of questions and accessing these properties inside that dictionary so we'll say for question Q in data of questions and that's going to return a list then we'll say that the new question equals to a question object because remember we have to create a new object every time we loop through this and we'll say that the new question title or rather the question actually because that's what it is on the model equals to Q of title so that's the actual question that's being asked and then we'll say that the order equals to some kind of integer which will loop through over here we'll say order equals one for the first one and we'll say that equals to order and then we can say new question that's save and we'll increment the order at the end of the for loop so there's the new question now we need to assign the choices to that question so we'll say for choice in question of choices we'll say the new choice equals to a choice object and that new choice title will be equal to C which is what we're looping through and then we can just save the choice and then add the choice to the new questions choices so say dot choices add the new choice like that and then we just need to add the answer to the question as well so we'll say new question answer equals to the choice object that we created we don't want to create another choice object we can basically just fetch the one that was already created so we'll say choice objects get where the title equals to q of answer and then we can assign the assignment of this question equal to the assignment that was created at the beginning of this create method so this assignment here and then we can save our question and then tally our order by saying order plus equals to 1 and at the end of all that we can say return the assignment so there we go that's our create method and if we come back and click Submit it seems you've got an error connection refused so let's see why that is we assumed got from user dot model so this is meant to be from users and let's try that again click Submit and this time we get a 401 unauthorized and that's because we're not logged in so we'll just log in and we actually might just need to refresh the page here so we'll log in again and let's click on create we'll add a question now let's check that it wasn't created here and I guess I wasn't so that's good so this will be the first real assignment and we'll say this is is this cool so the answer is yes choices are yes and no and we'll add another question yeah and say does this work the answer is yes choices are yes and no submit we get a 500 error again let's see and it's telling us that there's a not null constraint which is the answer ID so let's go back here back down this is most likely happening because by default the serializer is expecting us to pass in an ID so let's just try and go to the models here and what I'm going to do here is say blank and null equal true and it's just to stop the server here and we'll just say make migrations and then say migrate and it's just runs over here and if we come back and submit this I'm getting the same issue on the API question assignment ID so again let's just add the blank and null equal true to that and this is obviously a temporary fix this is not something that actually makes sense so let's try it again now we'll submit it another 500 and now we're just getting get returned more than one choice so that means that it was actually created so let's go back into here and refresh this okay so we've got first the first three real assignment is created three times so let's just delete those there and let's see what we need to get rid of let's just get rid of all those yes or knows and did that and then we can go to the questions you've got does this work on question two okay so now let's click Submit and okay we're returning to again so that's that's delete everything okay cool now let's try it again or click Submit and okay I can understand why this is happening now it's because we're passing in the choices as yes and no for both of these questions so what's happening in the serializer is that it's creating those without even checking if they are actually existing so another way to do this would just be to use the get or create method but what I'm going to do is just for the time being we will just delete those and change the answers that we're submitting so we can come back here into this and we'll say does this work on so let's just make it true and we'll say choices are true and false and if we click Submit now we didn't get any errors there and maybe a post request returned to o1 and if we go back to the home view there's the first real assignment and okay so we've got this navigation error let's go fix that and we can navigate into source and then the assignment list you can just close that there and this is not meant to go there this should rather go to the ID there so we'll just change this to be item dot ID and that should work so let's go back home here and I'll click on now and it takes me to number seven cool there we go so we've implemented the create form pretty much correctly there's one or two problems that exist and I'm sure those can be fixed but I'm not really too worried about exactly how functional that is we can always tweak that later and the bottom line is that we were able to get this form to work so now you can create these assignments here on the front end and see them in this list display meaning that they are created in the back end so now we're able to create assignments and what we want to do to finish off is to add some functionality to create a graded assignment so if we take a look at the API models we originally created these four models and one of them is the graded assignment which basically is just created once somebody actually takes this assignment and actually just fills in the answers and clicks to submit the assignment so what we want to do is just add functionality to handle that in the back end and also display the person's created assignments on their profile and so if you'd like to follow along you can go to get up to our teach me django repository and head over to the commits the last one was this assignment creation working commit where we finished creating the assignment logic on creating those assignments in the backend and so this is where we'll be continuing in this one so once you've got everything ready and your editor then let's get started [Music] so what we're going to do to get started is create a graded assignment list view which will inherit from the list API view from the Django rest framework and so what we'll just do is come to the bottom here off to the view set and we'll just create a class and call this the graded assignment list view and we're going to import from Django's generics to handle that so we'll say from the rest framework that generics import the list API view so we'll inherit from that list API view here and that means all we need to do is to specify the serializer class which will be the graded assignment serializer so we don't have that yet so we'll just go and create it now and so we'll just call this the graded assignment serializer let's just copy that right there and we actually need to import this modelled in so this will be the graded assignment serializer which will just inherit from the model serializers and again we'll specify the class meta where we will specify the model as the graded assignment and will say that the fields are all the fields and so if we think about what all those fields are it would be the student the assignment and the grade now just like how we have in the assignment we have the teacher which is using the string serializer to display the user via its username so I'm going to do the same thing for the student because otherwise we're going to get the student ID and that's not useful so we'll just say student equals to string serializer many equals false and so now we just take that graded assignment serializer and we just imported here so from dot serializers and we specify that is the serializer class and we can also set the query set to be the graded assignment objects that all and so this assignment ListView actually will need to import the model day as well we'll take that ListView and we're going to go into the graded assignment URLs and currently we have the default routes a but we're not going to use the Rooter instead we'll use just our custom views so we'll just create a list there and we can get rid of that and say from API dot views import graded assignment list view and we'll say from Django dot URLs import path and then here we'll create a path which goes to just this empty string and then use the graded assignment list view dot as view and we can get rid of that day as well cool so everything seems to be working and we can head over to the localhost and if we go to graded assignments then we're going to be asked for authentication credentials so let's create the logic here on the profile to display a list of graded assignments so we'll come back here and go to source and then into containers and to the profile and so we need to actually make sure that we're being sent to the correct URL because it's meant to be profile / - and now we see that username there so let's just go to the layout and this is meant to go to profile that link there and there we go and so we basically just want to return a list of items so we'll just go here to list from nd and we'll take the same thing we used earlier so we'll copy all that and just come down and paste that beer and all we need is this large size there and we can go and delete all of that there and then what we'll do is inside the stove well then just paste all of that there and we'll make sure that we wrap that inside an h1 and actually just get rid of that h3 there as well and the data source I'll just make an empty list for now we can remove the header and the footer and we need to make sure that we import this list here at the top so we'll just paste that there and there we go now let's check it over here cool so that now we're just getting no data coming through and we want to use a component here which is basically like a progress component so if we just go down you'll see this here and a feedback and we get different kinds of progress components I'm just going to use the mini circular progress bar and it's very simple to use we'll just copy that and we'll just go into the components and return a result jeaious component here we'll say import react from react and we'll say that our constant result takes in props and then just returns a progress item so that's import that at the top like this and all we want is one progress item and we can actually just use parentheses like this so it's going to return a progress item like that and the percent is going to be equal to props grade which will pass into the component and the width we can keep there just like that and I'll just say export default result and then that result we can take into the profile here and say import result from that components result and we will render each item to be a result instead of being a list item so this will be result and this will just say is a assignment so for each assignment we'll return a result where the key equals to the assignment ID well graded assignment ID and the grade is equal to the assignment dot grade like that and now we just need to pass in the data source as the information that we get as the dot we get from the back end so we're going to go and create a new reducer to handle all of that so inside the store we've got the assignments and we'll just create another one here which will be the graded assignments j/s and it's going to be similar to the assignments that we have you already so I'm just going to get everything from the get assignment list and paste that all in there so we've got get assignment list start and we're going to need to add new action types in here as well and this could be just something like this get graded assignment list start fail and success and then we can use this here in our graded assignments actions so we'll call this one the get graded assignment list start and then get graded assignment list success and get graded assignment list fail and then this will be get graded assignments and we're going to need to take in the user name as well we could also filter the users by the token but we'll just pass in the user name to make it easier and instead of getting assignments this is going to go to graded assignments instead and we will do the same kind of thing here will dispatch the get graded assignment goes to start and get greater Simon to success and get graded assignment list fail and just pass in the error there cool so that's the methods that look to be taken care of and we just need to do the same thing in our reducers now so we'll create graded assignments jeaious and this will be the same sort of thing as what we have here in the assignments so everything from there I'll just paste that there and then we need the reducer here so we'll copy that paste that there we don't need a lot of these here so let's get rid of all of that there so we only have these three and we don't need the current assignment either those will be assignments this will be get graded assignment list and there and there and this will be get graded assignment list start which will dispatch this one and then we'll just put the rest of them in yeah and there we go that's pretty much our reducers taken care of there and our actions so we can close that one there and I'm just going to keep this one open for now so we'll head over to the profile and here we're going to use the same kind of logic as we did in the assignment detail we'll just copy the component did mount and will receive props and then we'll add those methods in there and we are giving the token already so if the token is undefined oh it's not undefined rather then we're going to dispatch a method and we're going to import that from our graded assignments so this comes from store actions graded assignments and this is the get graded assignments so we'll say this stuff props get graded assignments which we'll take in this dot props username and the token and then the same thing here dispatch get graded assignments with new props username and new prop star token and we've got both of those in the state there and then we just need to pass in the get graded assignments method here which will take in username and token and we will dispatch get graded assignments of the username and the token just like that then we pass our map dispatch to props inside the connected and let's see what this looks like so let's just refresh that there and cool so now we just need to pass the graded assignments into our state with state dot graded assignments dot assignments and we need to get that reducer in there as well so let's go to the index.js file and we'll just copy this one and make this the graded assignment reducer and make sure that this comes from graded assignments and then this will be graded assignments which is the grade an assignment reducer cool so we've got that set up and now we can access that via the state and now we just need to pass this as the data source and list so like that and this is actually min to either stop prop stop graded assignment and cool so now let's go into the admin and we'll create a graded assignment so just add one day we'll say the student is math assignment is the first real one and we'll say 50 is the grade now if we come back here and refresh that and we just needed to add the correct action names here or action types rather and now if we check if it works cool there we go and we can actually get rid of the bordered in this table and if we come back here there we go and lastly we can also add the loading here which will come from States dot graded assignments dot loading and we'll just come in here and say if this dot props dot loading then we'll return a skeleton so let's grab the skeleton from there and we'll just say turn the skeleton with active otherwise all this stuff will be rendered out and we'll need to get a higher-order component in this I'll say import the hoc which comes from hoc and this is just hoc like that and we'll just wrap it like that instead of the div and we'll also return it around this as well cool now we come back and there we go now the only issue is that instead of returning the graded assignments for the user Matt we're returning all of the graded assignments and that's not what we want to do we win what we want to do is actually filter this inside our view so let's go back to the API and then views and here in the graded assignment list view we're saying that the query set is equal to greater designed objects at all so that means that for every single person who uses the ListView they're going to get all the graded assignments back and that's obviously not what you want you want the assignments that you have completed so what you can say is define get query set and this just takes in self and then we'll start off by saying that the query set is equal to all the objects but then we will get the user name from the URL so basically what we'll do is we'll query instead of graded assignment let's just find this here in our actions instead of querying it like this we're going to pass in an extra parameter here which will be username equals two and then we'll just output this dynamically and that will be the username that's being entered in the function here so this kind of query is what we'll look for in our view so over here we'll say that the username equals to self dot request query parameters dot get the username or none and we'll say if the username is not none then we'll say the query set equals to the query said we currently have and then fall to that where the student double underscore username so basically the users username is equal to the user name and then we'll just say return the query set whichever that may be so now if we come back we're obviously going to get the one that we created but let's go back to it and change this to be the test user and if we refresh this now now we don't get that data coming through and okay we're not logged in either so let's login as well so let's go to profile and now we see hi Matt and no data coming through because this one is not for the user Matt so now we know that that's working and we're retrieving the graded assignments that are for that specific user so now all we need to do is just whenever we complete an assignment like this one then once we click that submit button here all this done will actually change that button name so we'll just go to the source containers and then assignment detail and let's just go down here and this is going to be inside the the questions so let's go to containers questions and then this will just be submit like that and if you click Next now the button says submit and when you click Submit it will process this in the backend so that's also instead of saying message success like that what we can do is just handle this here will say handle submit and what we'll do is just grab that there and call this dot handle submit and come back in here say paste that there and then we'll do the rest of the logic there and actually instead of handing the submit here we already have most of the logic on the assignment details so I'm going to cut that out and paste that there and then here when we click the submit button will call this docprops/meta.xmlpk ándale submit and we can actually just make sure that we call this function like that and we'll do the same thing here so when we handle submit we're going to say message dot success so that comes from Andi so we'll import it like this so now we have it here so we'll say submitting your assignment and so now we just need to handle the logic in the store where we will create a graded assignment so we'll just go to the store assignments and I'm just going to copy the create assignment method here I'm not going to handle all of the reducer stuff so we'll just go in to graded assignments like this and just create our function like that and this will be create graded assignment which will take in a token and assignment and it will post to graded assignments like that and we won't dispatch any method cyclist either so basically we're just posting to the server and we'll just say console.log success if it went through correctly and so our assignment needs to actually have a few things it needs to have the assignment ID that it corresponds to it needs to have the answers that the user provided so that we can verify that on the server and it needs to have the username of the person that created the assignment and we're going to bring this into the assignment detail so it will just import it here and then we'll take this graded assignment here and we'll say this props create graded assignment and come all the way to the bottom and add our method here which we'll say takes a token and assignment and say dispatch create graded assignment of the token and the assignment and so now when we call this method over here we're going to need to pass in this dot props token and then a assignment as well so the assignment we can just say constant assignment equals to an object and we'll say that the user name is this dot props the user name and then we need the assignment ID and we'll also need the answers so our way answers are the user's answers to the assignment and the way that we can pass in the assignment ID is just by accessing this dot props dot current assignment dot ID where the current assignment is here in the state already and then the answers we'll need to somehow store which we already are we're storing that in the state we have the user answers like that so we'll just pass that in as the user answers like this and then just say create the graded assignment with the token and the assignment like that and so let's see if we've got any errors you've got user answers so this is meant to be a clone of that so we'll just say constant user answers equals to this dot state and there we go so let's just select this is this cool and does this work true click Submit and we get method not allowed on graded assignments and that's correct because we haven't set up a path to handle that yet so let's bring this to the front there and currently we only have the assignment list view so let's import the create API view as well and then we'll say class graded assignment create view which inherits from the create API view we'll say the serializer class equals to the graded assignment serializer and we'll set to the query set equal to the graded assignment objects dot all and so we're going to need to override the method of creating the graded assignment because we're passing in data that it's not really understanding or knowing how to handle so if we take a look at the serializer then here we have the graded assignments serializer and we can close questions and graded assignments for bit so just like how we overrode the create method on the assignments you realize we're basically going to do the same thing here for the graded assignment so we'll just copy that there and paste this there and we'll go to the view here and we're going to override the method of creating on this create API view and the way that you do that is just by overriding the post method so we say define post which takes himself and basically we're doing the same thing as what we did here in the assignment view set so let's just take all of that there and paste that there so again we're taking a serializer in this case it's the graded assignment serializer pass in the request data if the serialize is valid then we'll say that the graded assignment equals to serialized dot create the request where we'll handle the create method here and if there is a graded assignment then return an HTTP to a-1 and otherwise that and now we just need to work on the logic here and so for the time being let's just go and print out the data so that we can see it come through so we'll say submit and if we come back here to the terminal then we're getting that method not allowed right so let's open up the store again just to fix that URL and we'll say that this goes to slash create and then you know URLs will create a path here which goes to slash create which will be the graded assignment create view which will handle this for you like that cool so we can close that and now if we come back here and do it again now it's just a bad request so if we check that and so let's just go back to the view here and we see we are using the graded assignments serializer we're passing in the request data and let's just create a print here to say print the request data like that now if we come back click Submit so we see assignment ID is 7 and then we get the answers as one being yes to being false however we're not getting the username which is the stock prop start username so if we come down here let's just add that one in there use name is state dot or dot username now if we come back here we'll submit it again and if we come back here now we've got the username coming through there and so let's try and handle this in the create method now so basically what we want to do is grab the assignment that has an ID of 7 so let's make sure we have everything imported here we do so we'll say that the assignment equals to assignment objects dot get with ID equals to the data of assignment ID and then we also want to get the student corresponding to the username source a student equals to user dot objects get where the username equals to data of username and now we want to create a graded assignment source a graded assignment equals to a graded assignment like that and we'll assign the assignment as the assignment we just grabbed like that and let's just bring us down a bit we also want to assign the student equal to the student that we grabbed here as well and now basically we want to compare each questions answers to the answer that the user selected and basically to store like a like a count of how many they've gotten right and then compute how many they got right as the percentage of how many questions they were and assign that as the grade so what I'm going to do is say that the questions equals to a list of questions for all the questions in the assignment so this assignment that we grabbed here we're going to say this is equal to Q for Q in assignment questions all so that will basically take all of those question objects and store them in this list and then the next thing we're going to do is grab the answers from the request status answers so if we look at this object again answers is an object with the keys being 1 & 2 & etc so one way that we could do this is by saying that the answers equals to a list of data answers of let's say a for a in data of answers basically what we're doing is were saying for every key inside data of answers get the value that's why we pass in a inside the list to index the key from data of answers remember data of answers is a dictionary so we get all the keys from the dictionary and then get the value of the key from inside the dictionary and we're basically creating a list of values from the dictionary and then what we just do now is just compare the answer for question compared to the answer inside the answers list so we could just say for I in range of length of questions so we'll perform the loop however many questions they are and say if questions of I to access that first element of the questions list dot answer that title is equal to answers of I so what that means is that if the answer of the question we just checked in the list is equal to the user's answer then we'll add one to the users count so we'll just say that the answered correct count equals zero and then here we'll say onto the correct count plus equals one and in here we'll just increment the counter I to loop through the next item in the list so it'll go through all the items in the list and then you have an on-set correct count which will be how many they got right and the length of questions is how many questions they are so we just say that the grade equals to the answered quick count divided by length of questions and then we'll just say that the graded assignment grade equals to the grade that we just calculated and then we'll just say graded assignment let's save and return that graded assignment and there we go that's our method of creating the graded assignment so if we check everything is still working so let's come back here and click Submit and we're still getting a bad request on this URL and that's most likely because we don't have a student that corresponds to the user that just submitted this so let's go back to home and we actually haven't registered that model in the database so let's go to users and then admin and we'll import the student and then at the bottom here we'll just copy this one here and say this is the student and come back here and refresh this now you've got the students there and of course we don't have the student format so let's just create a student day and save this as Matt and now if we submit it we're getting another one here so let's go back to the assignment and see why this is and so what I'm going to do is actually just get rid of the if statement here because most likely the serializer is not valid so we only just need to call that so let's just do it like that and if we come back in here and submit this now we get success so if we take a look in the admin and go to graded assignments now we can see to come through there and this first one is worth 50% and let's just see why that is if we go back here we said isn't is this cool yes does this work false let's say this is true and submit it now and if we go back here and check the latest one now we get one and what we can actually do here in the serializer is if we come down we can say that the grade equals to this times 100 so that now if we submit that come back to graded assignments now it's 100 and we can go to our profile and yeah so that's why we were getting 0.5 percent 0.5 and 1 percent whereas it should be a hundred percent cool so now those methods are finally working and we've basically completed everything that we set up from the moment we demoed the application which was the ability to create custom users to actually get that data in the front end store everything with authentication to create assignments and I know we're not adding too many validation checks to see if the user actually is each or not but those are small things that you can add in to complete everything and then lastly we added the functionality to create a graded assignment which is very cool so all you do is just fill in the answers to the assignment and there you go it creates the graded assignment for you yes you can fill in that form as many times as you want it's not actually checking whether you've done it before so again there aren't many validation checks in place but that's besides the point it's more to show you how you can create the different users and get that data across into the front-end because that's really the biggest effort is it's in learning how to customize those serializers learning the methods that you can override and it gets really tricky when you have nested relationships and foreign keys so learning about serializers can actually be quite beneficial as we've seen so that ends off this tutorial series for the time being if you enjoyed this video make sure to leave a comment down below and let us know what you thought about the series and if there are any other things that you think we should be adding into it or concerns that you have and other than that thanks for watching don't forget to subscribe and we'll see you in the next one
Info
Channel: freeCodeCamp.org
Views: 133,615
Rating: undefined out of 5
Keywords: django, django tutorial, python django, python, Django Web Framework (Software), Python, python programming, python 3, python 3.5, django python, python tutorial, django 2.0 tutorial, django react, django rest framework react, django multiple users, django school system, teach me django, django school management system, django react tutorial, react school system, django course, django tutorial for beginners, react tutorial, javascript
Id: JIFqqdRxmVo
Channel Id: undefined
Length: 197min 8sec (11828 seconds)
Published: Tue Apr 23 2019
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.