Heads up! To view this whole video, sign in with your Courses Plus account or enroll in your free 7-day trial. Sign In Enroll
Preview
Start a free Courses trial
to watch this video
Mixins, small classes that add or augment a single feature, are an excellent way to customize and modify your views.
I absolutely love mixins for class-based views and find them to be the right balance of customization bonuses versus code and mental work.
If you want to know more about mixins, you can read the official guide to them or check out django-braces for example code.
When you work with classes,
0:00
often the easiest way to customize
a class is to just extend it and
0:02
remove, override or add the attributes or
method that you don't want.
0:05
That works fine most of the time.
0:09
Sometimes, though, you need to be able to
do this manipulation in lots of places.
0:11
So you bring in another class because
you don't wanna repeat yourself, right?
0:14
These little classes are called mixins.
0:18
You probably remember me showing you
them back in object-oriented Python.
0:21
Well, they're coming back.
0:24
Django provides a lot of mixins for
use in its class-based views.
0:26
Django also provides some mixins for
handling authentication in your CBVs.
0:30
It's also pretty easy to make your own
mixins if you need them, and, of course,
0:34
the Django community has
provided some mixins, too.
0:37
Come over to Workspaces with me and
0:40
learn how to build your views
from some smaller blocks.
0:42
So in the last video, I mentioned
that CreateView was looking for
0:45
the self.object thing
that it couldn't find.
0:50
So how do I know that?
0:55
Well, I've spent a lot of time
with class-based views, but
0:56
also there is this absolutely
amazing website, ccbv.co.uk.
1:00
I will put a link to it
in the teacher's notes.
1:04
And on this site, there is really,
really great documentation for
1:07
all of the different class-based
views that Django provides, and
1:11
also all of the mixins.
1:16
So, for example, I can look through here,
I can see the classes and
1:17
mixins that end up creating CreateView.
1:22
I can see all of the attributes
that CreateView has,
1:25
what their default arguments are,
and where they were defined.
1:27
And then I can also look
at any individual method.
1:33
If there's also versions of that method,
1:35
you get to see each of the places
where that method is defined.
1:37
And then I can look in here and I can see
that there is the self.object = None,
1:40
and that's the one that created it,
which is what we wanted, so awesome.
1:45
I highly, highly recommend
using the site constantly.
1:50
I use it myself all the time.
1:52
So I mentioned mixins, there's all these
mixins up here like ModelFormMixin.
1:54
And so mixins are small classes that
will handle specific little bits and
2:01
pieces that you need to have
added to your classes sometimes.
2:06
So, for instance, the ModelFormMixin is
a mixin that provides a way to show and
2:11
handle a model form and a request.
2:15
So this handles instantiating model forms,
putting data into them,
2:16
sending them out to the template,
validating them and
2:20
handling what happens if they are valid or
if they are invalid.
2:24
I suggest that you read
through these methods and
2:28
you will see exactly how that works.
2:30
It's surprisingly straightforward.
2:32
One of the things that I wanna do
in my views over here, though,
2:35
is I don't wanna use Django's
mixins to be like, well,
2:38
let's make CreateView do this thing where
it selects a bunch of records or whatever.
2:41
That's easy, that's ordinary and
that you and I were better than that.
2:46
What I wanna do,
I don’t wanna add some extra features.
2:52
I wanna add the requirement
that the CreateView,
2:56
the UpdateView and the DeleteView,
3:01
they all require you to be logged in
whenever you are trying to view them
3:03
because only logged in users should be
able to create, update or delete teams.
3:09
And I also wanna make it
easier to set this page title.
3:15
I have this really long block
of template level logic, and
3:18
I'd rather have this in a view,
then have this in the template.
3:22
So two things I wanna
implement with mixins.
3:26
So the first thing to do is to make
this to where it requires login.
3:28
And this is actually pretty easy
to do because Django provides
3:35
a mixin called the LoginRequiredMixin.
3:40
Cool thing, this mixin and these other
mixins that are here under Auth Mixins
3:43
are based on a code that a friend and
I wrote.
3:48
So it's neat getting to see
code very similar to my own.
3:51
So I'm gonna copy this,
which is the import statement, and
3:56
I'm gonna bring it back
over here to my views.py.
4:00
And as contrib comes before core,
that's gonna go at the top.
4:04
And then on CreateView,
4:08
I'm going to add LoginRequiredMixin.
4:11
And I'm gonna add it to the left
of CreateView because I want
4:16
the LoginRequired to happen first.
4:20
If a user isn't logged in,
4:22
I wanna kick them out before
the CreateView ever really gets started.
4:24
So let me make sure that
my server is running, And
4:28
then I will come over here
to an incognito window.
4:34
And if I try to go to /teams/create,
I get this 404.
4:41
And I get a 404 because Django is trying
to redirect me to this accounts login,
4:48
which is the default login page.
4:52
That doesn't exist.
4:54
I'm not gonna build that because
auth isn't part of this course, but
4:55
you are certainly welcome to try and
figure that out and go ahead and build it.
4:59
Other than that, keep your eyes open for
other courses about how to do auth.
5:03
But we know that it works, right?
5:08
You can see here that I was given
this 404 because I'm not logged in.
5:09
I'm being sent to a login page, and
it will redirect me to this teams/create.
5:13
So the login thing that I wanted
to have work worked, okay.
5:18
So I'm gonna go ahead and
add that to these other two views as well,
5:24
LoginRequiredMixin and LoginRequiredMixin.
5:30
All three of those views
are now login required.
5:35
So great, that's really easy to handle.
5:39
Now if we're gonna do this kind of thing,
it doesn't make a lot of sense to have
5:43
these update and
create things on these other pages.
5:48
They all need to be wrapped with this
is_authenticated thing or just removed.
5:53
I would probably just remove them, but
5:58
again, I'll leave that up
to you to do if you want.
6:00
Okay, so I talked about using
Django's mixins, right?
6:03
We have this LoginRequiredMixin
that you've used.
6:09
How about when you wanna
make your own mixins?
6:12
So let's make a mixin.
6:15
So here inside teams,
I'm gonna make a new file.
6:18
I'm gonna call it mixins.py.
6:20
And inside here, I'm gonna make my mixin.
6:23
So what do I want my mixin to do?
6:26
I want my mixin to let me set an attribute
on the class called page_title and
6:29
that will get added to the context.
6:33
It will just be this page title
that's automatically added.
6:35
Now why do that instead of
overriding get_context_data?
6:37
Well, if I wanna set a page
title on 20 different views,
6:42
I have to go override get_context_data
on 20 different views.
6:46
I'd rather do that not
on 20 different views.
6:50
I'd rather just set an attribute.
6:53
But because not every page
title is going to be,
6:54
it will be set as straight
text that never changes,
6:58
we need to also provide a method that lets
users programmatically set a page title.
7:01
So we have two things to accomplish, we
have to have an attribute and we have to
7:07
have a method and we need to make sure
that the data gets into the context.
7:11
So class PageTitleMixin, and I'm gonna set
7:15
page_title = an empty string,
def get_page_title.
7:21
And here,
I'm just gonna return self.page_title.
7:29
And I know the self.page_title
exists because I did this.
7:33
Okay, easy enough.
7:36
But now,
I need to override get_context_data.
7:38
And, if you remember correctly,
that takes self and kwargs.
7:42
And we're gonna get whatever
the current context is,
7:47
Because we don't know what other mixins
have been applied to the view or
7:54
what other views have
been applied to the view.
7:58
We don't know what the state of a view is
at the point where it gets to this mixin.
8:00
And then I'm gonna set page_title
to be equal to self.get_page_title.
8:05
So we get to the get_context_data.
8:11
It's gonna call self.get_page_title
in order to get the page title and
8:15
add it to the context.
8:19
That will in turn return
whatever this attribute is or
8:21
whatever this function this method
ends up being at that point.
8:24
And then return context.
8:29
So this mixin is pretty straightforward.
8:30
This pattern of having an attribute and
8:33
then having a method that all it does is
return the attribute is really, really
8:37
common because this gives you two handy
ways to get the same data set on a view.
8:42
You can either set it as an attribute if
it's static and is never gonna change, or
8:50
you can set it in a method if you need to
be able to programmatically calculate what
8:54
this is, or maybe you need conditionally
to change certain things, whatever.
8:58
This pattern here is really, really
good pattern to adopting it used to.
9:02
Okay, so
I think I'm ready to use this in my view.
9:07
So I'm gonna come back
over here to views.py, and
9:12
I'm gonna do from .import mixins cuz
that's how we do all of this stuff.
9:17
And the two views that have this
problem are the CreateView and
9:25
the UpdateView, so
those are the two that I wanna change.
9:29
So I'm gonna leave LoginRequiredMixin
as the first because,
9:33
again, I wanna kick them
out if they're not in.
9:36
And then in the CreateView,
9:39
I wanna just add mixins.PageTitleMixin.
9:43
And on this one,
9:48
I can actually just set the attribute
because it's not going to change.
9:49
So page_title = "Create a new team".
9:54
But on TeamUpdateView, which I also want
to add the mixins.PageTitleMixin too,
10:01
I don't know what the team name is
gonna be, so I wanna use the team name.
10:09
So I'm gonna override get_page_title,
and it just takes self.
10:16
And I'm gonna use another
method called get_object,
10:21
which gets the object that's
currently being edited, and
10:26
I'm gonna return Update blank and
I'll format that with obj.name.
10:31
Okay, so I'm using the mixin in
10:37
both of the ways that I've just
talked about it being usable, right?
10:39
I'm setting it here as a static
attribute that's never gonna change.
10:43
And here,
I'm programmatically building it.
10:48
I'm creating it through code.
10:52
So cool, that's very handy.
10:55
Now the cool thing is that both of
these two views use the same template.
10:57
So to actually output this,
I only have to change one thing.
11:01
So I can delete all of that and I can just
print out page_title, and I can hit Save.
11:05
So again, I'm gonna restart my server.
11:11
I was having some issues with the server,
it was restarting constantly.
11:16
So if you aren't having those issues,
11:18
don't feel like you have to
constantly restart your server.
11:20
So let's hit Edit on the Adders here.
11:24
I'm gonna edit them.
11:27
Okay, cool, so it says, Update Adders.
11:28
And if I look over here at my view,
it should say Update and
11:30
then the team name, which it does, okay?
11:35
And if I go to add a new team,
I now get Create a new team,
11:38
and that is what I set right here.
11:43
So that's pretty cool.
11:46
I saved myself a lot of time and trouble
11:48
by just creating a mixin that does this
little tiny bit of work that I need done.
11:51
You can make mixins like this
that handle all sorts of small
11:57
little problems that come up
on your project so that you
12:00
can make solutions for yourself quickly
that you can reuse multiple places.
12:06
We could use this mixin on every single
one of our views if we wanted to, right?
12:11
And that way,
it's just there for us to use.
12:17
Part of making lives easier,
I actually wanna show you,
12:20
A project, this is the one that
I made that has the mixins, and
12:28
my friend Chris Jones and
I did this together.
12:33
So if you find yourself using class-based
views a lot, this is a, I think,
12:36
really good package of mixins to go and
look through to find things that you're
12:41
like, I need to handle form
valid messages or whatever.
12:46
So I'll put a link to this in
the teacher's notes as well.
12:50
Mixins are the real power
inside of class-based views.
12:54
And you'll do yourself a big favor
to get comfortable with them,
12:56
learn which ones are available and
what they do.
12:59
And not to toot my own horn too much,
but libraries like django-braces and
13:01
others can save you a lot of time when
you needed to tweak how CBVs work.
13:05
You need to sign up for Treehouse in order to download course files.
Sign up