WEBVTT 00:00.450 --> 00:05.520 So currently, our API allows us to create posts and also list them out. 00:06.120 --> 00:12.600 A really awesome part of Reddit, the sort of the magic, in my opinion, is when users can upvote these 00:12.600 --> 00:16.570 posts so that they can see, you know, what are the most popular things on the Internet. 00:16.590 --> 00:20.460 Right now, they call Reddit, sometimes the front page of the Internet because it's like these are 00:20.460 --> 00:23.040 the things that, you know, most the users are interested in. 00:23.070 --> 00:26.580 These are kind of cool things or important things of the day. 00:27.060 --> 00:32.580 So we want to create upvotes or vote objects for our project if we come back to our code. 00:33.180 --> 00:40.350 If we look at our models that pi a vote consists of a user and a post that that user wants to upvote. 00:40.500 --> 00:45.420 So we're gonna do the similar thing for the vote here like we did in the post to say, you know, whoever's 00:45.420 --> 00:48.540 making the call will that's going to be the user, the voter. 00:48.960 --> 00:53.040 But then we do have to, you know, figure out what post it is that they're trying to make this vote 00:53.040 --> 00:53.370 for. 00:53.670 --> 00:59.220 And the whole reason we did this this way again was to make sure that someone doesn't vote for something 00:59.220 --> 01:01.470 twice or else they could really game the system. 01:01.470 --> 01:01.710 Right. 01:01.980 --> 01:06.480 You have to have separate accounts voting for something in order for that number to go up. 01:07.620 --> 01:14.280 So if we're going to have an API to create a vote, the first thing that we have to do is have a serializer 01:14.550 --> 01:15.450 for that vote. 01:15.870 --> 01:19.110 So let's go ahead and make a new serializer and I'm going to copy. 01:20.080 --> 01:26.900 What we have here for the same line of class come down on a set of being a post serializer. 01:26.920 --> 01:31.840 I'm going to call this a vote serializer to copy this meta stuff. 01:33.040 --> 01:36.120 OK, bring that in instead of the model being a post. 01:36.150 --> 01:38.220 It's going to be a vote object. 01:38.760 --> 01:42.600 And instead of having all the fields that a post has, it's very different. 01:42.810 --> 01:46.680 It could be tempting for you to say, oh, we have to bring in voter. 01:46.710 --> 01:47.710 We have to bring in post. 01:47.790 --> 01:52.290 But I do not want someone to be able to set those things. 01:52.290 --> 01:58.410 And really, when we think about it, I don't want someone when they're setting, you know, hitting 01:58.410 --> 02:03.600 up the API to say, you know, oh, this is the voter that I wanted to be in in the post. 02:03.620 --> 02:06.060 That's going to be all contained inside of the you are real. 02:06.060 --> 02:07.350 You'll see that in a second here. 02:07.830 --> 02:09.950 So really, this is all that we need for the vote. 02:09.960 --> 02:11.900 Serializer is just the I.D.. 02:11.940 --> 02:13.980 This is literally all we need. 02:14.180 --> 02:14.400 OK. 02:14.550 --> 02:16.110 So go ahead and hit save here. 02:16.590 --> 02:22.230 Now let's move over to our your ls to say, OK, how is it that someone is going to vote for one of 02:22.230 --> 02:23.400 these particular items? 02:23.490 --> 02:26.910 So we're going to make a new path and a copy what we have here. 02:27.230 --> 02:32.460 Loop's copy this paste down below and I'm going to say if someone wants to upvote something it should 02:32.460 --> 02:36.240 be API slash post slash the idea of that post. 02:36.250 --> 02:40.890 So let's maybe say one, for instance, slash and then we're gonna call it vote. 02:41.550 --> 02:41.830 OK. 02:42.690 --> 02:44.820 Now we can't just have the number one there. 02:44.820 --> 02:48.090 That's sort of a place holder for me to say, you know, how do I want this to look? 02:48.450 --> 02:52.980 Instead, what we're gonna do is we're gonna do angled brackets and then say we're looking for an ENT 02:53.520 --> 02:57.240 colon and we're gonna call this piqué short for primary key. 02:57.850 --> 02:58.260 All right. 02:58.650 --> 03:04.290 Now, as for where this is going to go, it's not going to the post list, but we haven't made the proper 03:04.290 --> 03:04.800 view yet. 03:04.830 --> 03:06.660 So let's go back to our Vieuxtemps pie. 03:07.320 --> 03:12.720 And instead of creating a list view, we want to create just a create. 03:13.080 --> 03:15.950 So I'm gonna go ahead and copy a lot of what we have here. 03:16.800 --> 03:17.160 Okay. 03:17.220 --> 03:18.890 We don't need this comment there. 03:18.900 --> 03:19.890 Let's get rid of that. 03:20.710 --> 03:24.000 Okay, so let's make a new class instead of being post list. 03:24.030 --> 03:26.970 I'm going to call this vote create. 03:28.040 --> 03:28.460 All right. 03:29.000 --> 03:33.530 And instead of being a list, create, because no one really wants to see individual votes. 03:33.800 --> 03:37.130 Instead, let's just have this be a create API view. 03:37.160 --> 03:40.940 So this is only going to be making new vote objects. 03:41.420 --> 03:46.340 Now, we have to do a little bit of, you know, changing of things here for the query set. 03:46.700 --> 03:51.320 It'd be really tempting to just say, oh, you know, go get all the different vote objects, but I'm 03:51.320 --> 03:53.720 going to show you why this is not what we're looking for. 03:53.730 --> 03:56.300 So we're gonna go ahead and get rid of this. 03:56.690 --> 04:01.510 And instead we're going to say the serializer class instead of being post serializer, this is going 04:01.510 --> 04:03.840 to be vote serializer, right? 04:03.890 --> 04:06.110 The same one that we had created right here. 04:06.680 --> 04:07.910 So we've got to import that. 04:07.910 --> 04:12.300 We're gonna say we're looking for the vote serializer. 04:13.230 --> 04:13.670 All right. 04:14.120 --> 04:17.890 Now, as far as permissions go, we want to make sure that someone is authenticated. 04:18.110 --> 04:21.020 Again, we don't want someone to be able to read this information. 04:21.020 --> 04:25.610 So it's just going to say someone has to be authenticated in order to use this. 04:26.300 --> 04:29.240 And then what we're gonna do this is what I was talking about before. 04:29.240 --> 04:34.730 We do have to provide a query set, but we have to be very careful because if someone's trying to create 04:34.730 --> 04:41.360 a vote, we have to make sure and see, you know, what particular vote that we're looking for. 04:41.360 --> 04:44.300 We're looking for a particular user in a particular post. 04:44.810 --> 04:47.720 So I'm going to do a function here called GET. 04:49.120 --> 04:51.580 Underscore, query set. 04:52.190 --> 04:52.460 OK. 04:53.250 --> 04:55.630 And we're going to put self inside of there. 04:56.320 --> 05:01.540 And we're going to say when someone is trying to get a particular object, we're gonna first grab the 05:01.540 --> 05:01.900 user. 05:01.900 --> 05:04.560 So the user is going to be equal to self. 05:04.680 --> 05:08.270 Dot request dot user. 05:09.110 --> 05:09.410 OK. 05:10.790 --> 05:15.440 And we're going to say that the post the post that the user is looking for is equal to. 05:16.500 --> 05:18.310 The post object. 05:19.520 --> 05:19.940 Dot. 05:20.000 --> 05:22.100 And let's make sure or not post. 05:22.140 --> 05:23.400 We want to get you. 05:23.840 --> 05:26.880 I'm getting confused between Votan post, but we are looking for a post. 05:26.880 --> 05:30.460 Your story is a capital post, dot. 05:31.170 --> 05:33.000 And then we want to do objects. 05:33.950 --> 05:35.350 And then we want to go. 05:38.280 --> 05:43.740 And this is where we have the parentheses, the primary key is going to be equal to whatever primary 05:43.740 --> 05:45.600 key was passed inside of here. 05:45.750 --> 05:50.370 So in order to get that information, we've got to say that this is equal to self. 05:50.760 --> 05:53.690 Dot k, w, args, k. 05:53.760 --> 05:55.980 That's how we access that piece of information. 05:56.510 --> 05:59.970 And we have to pass inside of this dictionary that we're looking for the primary key. 06:00.300 --> 06:03.330 OK, so we're still not done yet. 06:03.750 --> 06:06.840 The whole point of this function is to return a query set. 06:06.860 --> 06:10.340 So we are going to return a search for vote. 06:11.160 --> 06:14.780 Dot objects, dot filter. 06:15.330 --> 06:21.780 And we want to find votes where the voter is equal to the user that's currently making this request. 06:22.380 --> 06:28.320 And where they post is equal to the post that we just pulled up here via the primary key. 06:28.400 --> 06:28.670 OK. 06:29.190 --> 06:33.270 So since we're using that vote object, we've got to make sure that we import it from our models. 06:33.770 --> 06:33.950 OK. 06:34.020 --> 06:35.370 So we'll go ahead and add that. 06:35.910 --> 06:41.550 And now with this in place, we have the beginnings to be able to create something. 06:41.570 --> 06:47.250 So let's go ahead and copy the name of this vote, create come back to our your LS and say, OK, if 06:47.250 --> 06:51.530 someone goes to this, you are well, send them to the vote, create view. 06:52.380 --> 06:54.660 So let's go ahead and copy the swing and a copy. 06:55.220 --> 06:56.730 This Yoro that we have here. 06:57.270 --> 06:57.910 And let's look at. 06:57.950 --> 07:03.150 You know, let's go ahead and upvote the very first post that we have the one for zappy code. 07:03.170 --> 07:10.200 So I'm going to go ahead and say if someone goes to slash API, slash posts, slash one. 07:11.400 --> 07:13.640 OK, and wants to do a vote on this. 07:16.080 --> 07:17.970 Are we not running the server here? 07:18.990 --> 07:21.270 We've not set votes somewhere. 07:21.300 --> 07:23.480 Let's see, Serializer, is that pie? 07:24.470 --> 07:26.230 Guess we forgot to import that. 07:26.580 --> 07:27.580 Yes, OK. 07:27.660 --> 07:28.290 Copy. 07:28.350 --> 07:29.190 Capital vote. 07:29.400 --> 07:30.210 Save that. 07:30.810 --> 07:31.700 Save our your URLs. 07:31.790 --> 07:33.240 Looks like we haven't saved that either. 07:33.270 --> 07:34.470 Let's reload this page. 07:35.430 --> 07:36.090 And here we go. 07:36.270 --> 07:36.510 All right. 07:36.570 --> 07:43.410 So this is saying that someone here can create a post and notice it saying if because we visited this 07:43.410 --> 07:47.760 page, it tried to do it, getting it, saying, hey, there's no get method allowed for this particular 07:48.230 --> 07:48.890 your URL. 07:49.500 --> 07:54.440 But if we try and go ahead and do a post here, it's going to have some issues. 07:54.450 --> 07:54.660 Right. 07:54.710 --> 07:58.890 Like, it has to be able to know what user it is that it's trying to save this for. 07:58.910 --> 08:03.660 So this is going to be similar esq to what we did with the Post. 08:03.870 --> 08:06.060 We're going have to do a perform create. 08:06.540 --> 08:08.940 So go ahead and copy what we have here. 08:09.570 --> 08:11.530 We're going to add this down to this class. 08:11.580 --> 08:12.870 So perform, create. 08:12.900 --> 08:18.650 But we've got to do a little bit more work here so that when we do the serializer not safe. 08:18.660 --> 08:20.130 It's not the poster. 08:20.190 --> 08:21.780 It's the voter that we're looking for. 08:21.790 --> 08:27.940 But not only do we said that, but we also need to set what the post is. 08:27.970 --> 08:30.930 So we're going to say post is equal to. 08:32.010 --> 08:37.150 And this is where we want to grab exactly what we had listed up here, the post of objects. 08:37.210 --> 08:41.590 I get all this good stuff, so I'm gonna go ahead and copy this, paste that there. 08:41.690 --> 08:45.560 So now when someone saves this, the vote is going to properly go there. 08:45.560 --> 08:48.110 So let's go ahead and save this. 08:48.710 --> 08:51.890 Come back and let's reload this. 08:51.890 --> 08:52.600 You RLC. 08:52.730 --> 08:53.960 Let's do a post here. 08:53.960 --> 08:56.420 So I'm going to do a post and look at this. 08:56.600 --> 08:57.500 It creates a vote. 08:57.860 --> 09:01.160 And if we go back to the admin portion of the Web site. 09:01.590 --> 09:04.980 So this is just our Web site Slash Admon. 09:05.150 --> 09:06.170 And we go to votes. 09:06.470 --> 09:07.070 Look at this. 09:07.190 --> 09:09.680 We have a vote object and says, look, it's AP code. 09:10.250 --> 09:12.230 Voted for the first post. 09:12.950 --> 09:14.180 But there's a problem here. 09:14.660 --> 09:21.170 If we come back to our app and we wanted to do another post, look, it creates another vote object. 09:21.680 --> 09:22.010 Right. 09:22.220 --> 09:26.760 And if we, you know, reload the admin here and look at the votes now. 09:26.840 --> 09:29.460 Well, now there's two votes for the very same thing. 09:29.480 --> 09:35.240 So we could, you know, manually go in and check periodically if something's there and delete things. 09:36.080 --> 09:38.420 But this is not a great method for us. 09:38.450 --> 09:40.450 We want to make it and do a check and see. 09:40.460 --> 09:44.660 Has someone, you know, already voted for a particular post. 09:44.900 --> 09:50.150 So in order to do this, we're gonna come back to our code here before we do the create. 09:50.150 --> 09:56.740 Before we do this Dotts Save, we should check and see if anything came back from this query that you 09:56.750 --> 10:02.210 may be a might have been wondering why did we do all this work to go, you know, user and post and 10:02.210 --> 10:03.290 do all of this here? 10:03.850 --> 10:07.490 Cause, you know, currently the way things are, we could have abandoned all that. 10:07.490 --> 10:12.980 But this is the reason if we say if self dot get. 10:14.060 --> 10:14.990 Query set. 10:16.020 --> 10:18.770 K Dot exists. 10:20.500 --> 10:26.950 All right, with the parentheses here, this will check and see, hey, is there already a vote in the 10:26.950 --> 10:30.250 database that has this particular user in this particular post? 10:30.340 --> 10:35.770 And if there is, well, then we need to tell the user that, you know, this is not what they're looking 10:35.770 --> 10:38.950 for and we need to raise an error to the user. 10:38.960 --> 10:47.700 So in this case, we're going to say raise we're going to say capital validation, capital error. 10:48.350 --> 10:53.170 And we're going to provide some text in here to sort of tell the user of this API what's going on. 10:53.190 --> 10:54.230 So we're going to say something. 10:54.250 --> 11:02.130 I think maybe like you have already voted for this post, maybe I'll even add a smiley. 11:02.140 --> 11:04.210 So this is a friendly API. 11:05.230 --> 11:10.960 So with this, we've got to make sure that we import the code for the validation error here. 11:11.020 --> 11:13.360 So let's go ahead and go up to the top. 11:14.170 --> 11:21.760 We're going to do from Rest. underscore framework DOT and then we want exceptions. 11:23.090 --> 11:28.280 They import and we want that capital validation there. 11:28.790 --> 11:29.030 All right. 11:29.300 --> 11:36.560 So with this in place, I'm going to save come back to SSAFA here and I'm going to try and vote for, 11:36.560 --> 11:41.960 again, the very first post as the zappy code user if I do this post. 11:43.370 --> 11:43.880 OK. 11:44.280 --> 11:47.250 We get an error here, OK? 11:47.610 --> 11:49.380 I found the issue. 11:49.410 --> 11:54.240 But if you want to sort of follow along how I found the issue, this might help you when you're debugging. 11:54.600 --> 11:59.230 I always look for the name of a file that I have personally edited. 11:59.370 --> 12:05.220 If I see anything that is, you know, for example, inside of the, you know, the Django framework 12:05.220 --> 12:08.820 or the Python framework, I'm like, OK, I'm going to assume that code is OK. 12:08.870 --> 12:14.070 But if, you know, there's something like my Vieuxtemps Pi, I probably had an issue here. 12:14.190 --> 12:21.390 So if we go ahead and look at line 22 instead of reviews, Dot Pi, it's saying a vote has no attribute 12:21.450 --> 12:22.020 object. 12:22.740 --> 12:27.240 That is because it's supposed to be vote dot objects with an S. 12:27.450 --> 12:28.830 Yeah, that's what I miss there. 12:28.920 --> 12:36.540 OK, so if we go ahead and save that and now reload this page and I say, all right, I'm going to vote 12:36.930 --> 12:39.510 for the very first post and I hit post. 12:39.720 --> 12:40.590 Look what I get back. 12:41.070 --> 12:45.000 You have already voted for this post and a cool little smiley face. 12:45.210 --> 12:46.110 Isn't that awesome? 12:46.210 --> 12:47.460 OK, so it knows that we haven't. 12:47.820 --> 12:49.980 And I can keep hitting this button again and again and again. 12:50.430 --> 12:56.190 But if I move back to the Admon here, you'll notice I still only have that one vote object. 12:56.340 --> 13:02.220 Now, to really see if this code is working, we need to create a new user and see if that user is able 13:02.220 --> 13:03.160 to make an upvote. 13:03.750 --> 13:05.910 That is completely separate from the other object. 13:06.210 --> 13:11.390 And in order to test this, we're going to talk about another cool feature of the rest framework. 13:11.430 --> 13:13.080 Let's talk about that in the next lecture.