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