Overriding Methods8:01 with Kenneth Love
Django's class-based views are build on a _lot_ of methods. These methods provide the easiest way to customize your views.
If you've looked around on CCBV, you've no doubt seen the sheer gigantic number of methods that are available in your class-based views. Digging into these will open up a huge number of possibilities for you for customizing your views and getting just exactly the output that you want.
[MUSIC] [SOUND] Welcome back to 0:05 Django Class-based Views. 0:05 So far in this course, you've learned about several handy classes that Django 0:06 provides for you to make views from. 0:10 But all of these views end up needing special bits and 0:12 pieces of code to make them do exactly what you need. 0:15 You've already taken control of the get_context_data method, but 0:18 there are many other methods for customizing these views. 0:21 So join me in Workspaces and see how to make these classes work for 0:24 you even harder. 0:27 So a lot of times, you need to have a view that shows a group of items, 0:29 so like a DetailView or a ListView. 0:33 But you want it to only show items that appear in a particular queryset. 0:36 You can override the queryset attribute, which is just like queryset = whatever, 0:40 but you have to be very careful with that because querysets are mutable. 0:45 So you have to be sure to call .all at the end so 0:50 that it will actually go and fetch this fresh queryset, or 0:55 you have to do what I'm gonna do, which is to override the get_queryset method. 0:59 Either of these steps will let Django correctly clone the queryset 1:04 before it actually processes the view. 1:08 And without that, you get views that will show the same data 1:10 even though they should be showing different data. 1:13 It gets messy because of how the instantiation works. 1:17 So, I don't want anyone to delete a team 1:20 unless they're the coach of the team or they're a superuser. 1:24 So the DeleteView, like a lot of other views, 1:29 has this get_queryset method that, well, gets the queryset. 1:33 The queryset is a collection of data, even if it's only showing one item like 1:40 the DeleteView or the DetailView does, the view gets a queryset of items and then, 1:44 from that queryset, takes a single item. 1:49 So, that way, in controlling the queryset in general, 1:52 you control the pool of possible choices. 1:56 So this is generally the one that you wanna override. 1:59 So it's a pretty basic method. 2:03 It just takes one argument, which is self. 2:07 And then, inside of here, I'm gonna check to see if the request object, 2:09 which is the request that comes into the view, if the user on that is a superuser. 2:16 So if not self.request.user.is_superuser, then I'm gonna return 2:24 self.model.objects.filter(coach=self.requ- est.user). 2:29 Otherwise, if that if doesn't actually happen, 2:38 I'm just gonna return self.model.objects.all. 2:41 So, all class-based views have a request attribute on themselves, that is, 2:44 the request for the view. 2:49 You can use that to get to the current user and all sorts of other things. 2:51 Here, like I said, I'm checking to see if the user is a superuser. 2:55 And if they're not, 2:58 then I'll filter down the list of teams to only the teams that they coach. 2:59 I could use the reverse foreign key from the user. 3:02 That feels weird compared to using the model that's already associated 3:06 with the view. 3:09 If they are a superuser, though, then I'll just return all of the teams that exist. 3:10 So, that means I need to make another user and a team for them. 3:14 So, copy this over, go to admin. 3:22 Let's add another user. 3:26 So this will be testuser Test password, test password. 3:30 And then I want them to be able to log in, so 3:37 I'm gonna come check this Staff status, but 3:41 I do not want them to be a superuser. 3:45 So save that user. 3:49 Hop back over here, and I'm gonna add a new team, and this can be The Sharks. 3:52 I don't think I have a Sharks team yet, right? 3:58 I do, Polar Bears, testuser is their coach, 4:01 and the practice location is gonna be the Zoo Field, sure. 4:07 In case you didn't notice, I'm making those things up as I go. 4:14 There we go. 4:19 So there's the Polar Bears. 4:20 So, the next thing I'm gonna do is I'm going to make 4:22 a new incognito window, which is gonna go to admin. 4:26 And I'm gonna log in with my testuser. 4:33 So they're logged in. 4:37 They don't have permission to edit anything because they're just 4:39 an average everyday user. 4:42 So if I go to teams, then here's all the teams. 4:45 We've got everything set up. 4:48 So I should not be able to go to teams/delete/1 to delete the Tigers 4:49 because they are not the admin, or the coach rather, of the Tigers. 4:55 So I got a 404. 5:01 The reason I get the 404 is because when the view does 5:03 this queryset right here, they're not a superuser. 5:08 So we get back only the teams that they're the coach of, 5:14 which means we only get back the Polar Bears. 5:17 And the Tigers, the PK one, which is for 5:22 the Tigers isn't in the queryset which contains the Polar Bears. 5:25 There's nothing in there that has that PK, so pretty awesome. 5:29 There are a lot of other methods that you can override to get more customization. 5:34 Some are less common to use, of course, 5:39 while others are gonna be used all the time. 5:42 Get_queryset is one of the ones that's used a lot. 5:45 Another one that's pretty common to override is called get_initial. 5:48 And this method allows you to give initial or starter data to a form. 5:52 So I'm gonna use that here in the CreateView 5:57 because I want to make it to where the coach is automatically set, 6:00 it can be changed, but automatically set to the current user. 6:04 So get_initial(self). 6:08 And let's say initial = super().get_initial(). 6:12 And the reason I'm doing that is to get whatever the initial data 6:19 is if any has come through in the stack of calls for the view. 6:23 As it is with this just being a straight CreateView, 6:27 there shouldn't be any initial data, but it's better to be safe than sorry. 6:31 So then, we'll set initial["coach"] = self.request.user.pk because 6:36 coach contains a number, which is the ID of the user, or the PK of the user. 6:42 So, in this case, it's going to be self.request.user.pk, and 6:49 then I will return initial. 6:53 And this works pretty much just like the get_context_data did, 6:55 with the idea of you're pulling in this dictionary, you're changing a key and 6:59 then you're sending the dictionary back out. 7:03 Okay, so now, let's go over 7:06 here to teams/create. 7:11 Then I see that testuser is automatically loaded here for the coach. 7:16 And I can still select kennethlove, I could select nothing and have it fail, but 7:20 it's pre-selected on the current user. 7:24 So pretty awesome. 7:28 As you can imagine, these few methods are just the tip of the iceberg 7:31 when it comes to Django's class-based views. 7:34 This is actually one of the major valid complaints about CBVs. 7:36 They're full of methods and you have to know exactly how the view is constructed 7:38 to know what methods are available. 7:42 Luckily, the Django documentation is pretty solid here, and 7:44 there are great resources out there like CCBV. 7:47 I've put a link to CCBV in the teachers' notes. 7:50 So check it out the next time you decide to go spelunking in CBV's inheritance 7:52 chain. 7:56 If you were here in the Treehouse office, 7:57 you'd see me using this reference all the time. 7:59
You need to sign up for Treehouse in order to download course files.Sign up