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