1 00:00:00,320 --> 00:00:03,030 Our resources are ready for action, but they don't yet 2 00:00:03,030 --> 00:00:05,560 know how to take in input from our users. 3 00:00:05,560 --> 00:00:08,650 We need some way of telling them what pieces of data they should expect, 4 00:00:08,650 --> 00:00:13,600 like a title and URL for the courses, and also what those pieces of data should be. 5 00:00:13,600 --> 00:00:15,360 Title should be strings, for example. 6 00:00:16,490 --> 00:00:17,760 If we were doing this with models and 7 00:00:17,760 --> 00:00:21,042 views, we'd use a form or some other sort of validation library. 8 00:00:21,042 --> 00:00:24,410 Flask restful actually provides a validation library for 9 00:00:24,410 --> 00:00:27,800 us that works really well, it's called reqparse, and it's for 10 00:00:27,800 --> 00:00:29,730 parsing requests, let's go see how to use it. 11 00:00:31,180 --> 00:00:33,530 So once I get reqparse set up, 12 00:00:33,530 --> 00:00:37,560 I'm gonna be using Postman to test the API that I'm building. 13 00:00:37,560 --> 00:00:40,470 This is a good time for you to go and get it installed though, there is both 14 00:00:40,470 --> 00:00:45,670 a Chrome app and an OS X app, both are free and work more or less the same way. 15 00:00:45,670 --> 00:00:48,000 I'll put a link to their site in the teachers notes. 16 00:00:48,000 --> 00:00:51,310 I'm going to go ahead and put in the Chrome app though, because, 17 00:00:51,310 --> 00:00:52,730 you know, I'm running Chrome. 18 00:00:52,730 --> 00:00:56,850 And the cool thing is, 19 00:00:56,850 --> 00:01:02,490 it pops up here in your little bar and then you hit Postman and there's Postman, 20 00:01:02,490 --> 00:01:06,248 so cool, I'm going to skip that go straight to the app. 21 00:01:06,248 --> 00:01:10,780 Reqparse tells the API how to parse incoming requests. 22 00:01:10,780 --> 00:01:15,230 If you've used the Python module arg pars it's pretty similar so 23 00:01:15,230 --> 00:01:24,480 what I wanna do this over here and courses.py, I need to import reqparse. 24 00:01:25,940 --> 00:01:29,840 And then, I'm gonna add a parser to the course list thing here 25 00:01:29,840 --> 00:01:31,340 first of the course list resource. 26 00:01:31,340 --> 00:01:34,080 I don't know why I call it a thing, it's just a thing today. 27 00:01:34,080 --> 00:01:40,966 All right, so, inside init, we're gonna do self.reqparse 28 00:01:40,966 --> 00:01:45,750 = reqparse.RequestParser, 29 00:01:45,750 --> 00:01:49,770 sometimes you just can't predict the variable names. 30 00:01:49,770 --> 00:01:55,500 And so self.reqparse.add_argument, so we add arguments to 31 00:01:55,500 --> 00:02:01,590 the parser for each of the things that we want to have come in each of the fields. 32 00:02:01,590 --> 00:02:05,880 So for courses, I want to have one for title, I wanna have one for URL. 33 00:02:05,880 --> 00:02:07,500 So let's add title first. 34 00:02:09,060 --> 00:02:12,360 It is true, it is required, you have to have it. 35 00:02:12,360 --> 00:02:16,990 If you don't give it to me, I'm going to say, no course title provided. 36 00:02:16,990 --> 00:02:20,810 I could just say, no title provided, but either way. 37 00:02:20,810 --> 00:02:26,820 And then location is actually going to be a list, it's going to be form and json. 38 00:02:26,820 --> 00:02:34,580 So what this says is that, I need to tell reqparse where to look for this data. 39 00:02:34,580 --> 00:02:37,650 So, I'm telling it to look in forming coded data or 40 00:02:37,650 --> 00:02:41,750 to look in json data, which is in the body of the request. 41 00:02:41,750 --> 00:02:45,420 Whichever one comes last is the one that's looked at first, 42 00:02:45,420 --> 00:02:49,790 it's a little weird, but that's the way that one works. 43 00:02:49,790 --> 00:02:54,983 All right so let's add the other argument here, self.reqparse.add_argument, 44 00:02:54,983 --> 00:02:57,390 you can probably guess how most of this goes. 45 00:02:57,390 --> 00:03:02,272 It's going to be url, required=true, 46 00:03:02,272 --> 00:03:07,690 help=No course URL provided, 47 00:03:07,690 --> 00:03:11,950 and location is gonna equal form, and json. 48 00:03:11,950 --> 00:03:14,670 There are lots of other locations, I will link 49 00:03:14,670 --> 00:03:18,070 to that documentation in the teacher's notes, so you can check that out. 50 00:03:18,070 --> 00:03:22,790 Everything here is fairly straightforward, this is very similar to a forms library, 51 00:03:22,790 --> 00:03:26,840 where you're kinda specifying what all this stuff is. 52 00:03:26,840 --> 00:03:32,190 And by the way, if you're familiar with REST you might be thinking form here is 53 00:03:32,190 --> 00:03:38,570 form data and it's not it's the X dash dab dab dash form URL link encoded 54 00:03:38,570 --> 00:03:43,510 header which is like the standard one that HTML forms send. 55 00:03:43,510 --> 00:03:46,859 So the basically the idea here is you can send a form to your API and 56 00:03:46,859 --> 00:03:50,913 it'll work just like you were sending an XHR request or something like that. 57 00:03:50,913 --> 00:03:56,277 And then at the end here, I do want to go ahead and 58 00:03:56,277 --> 00:04:00,316 call super, and call init on that. 59 00:04:00,316 --> 00:04:03,280 All right, so there we go. 60 00:04:04,290 --> 00:04:08,000 This just makes sure that the standard set up goes ahead and it happens. 61 00:04:08,000 --> 00:04:12,630 Let's look over here at Postman, now the cool thing is you can you see this 62 00:04:12,630 --> 00:04:16,972 history thing you can save your post and stuff, which is kinda neat. 63 00:04:16,972 --> 00:04:20,290 So, let's come over here and 64 00:04:20,290 --> 00:04:25,209 get the URL, which is that one, all right. 65 00:04:25,209 --> 00:04:33,440 If I do a get to courses and send, then I get back Json. 66 00:04:33,440 --> 00:04:35,660 That's cool, that's exactly what we expected to get. 67 00:04:35,660 --> 00:04:39,080 Okay, so let's try and do just a blank post to 68 00:04:41,980 --> 00:04:44,840 it and I get back method is not allowed for this requested URL. 69 00:04:46,740 --> 00:04:49,696 You know what I forgot all about that, I didn't add a post, did I? 70 00:04:49,696 --> 00:04:53,660 All right let's go, we've got to get, let's add a post. 71 00:04:53,660 --> 00:04:58,093 All right it's a def post(self), all right, and 72 00:04:58,093 --> 00:05:02,545 then let's actually break apart these arguments. 73 00:05:02,545 --> 00:05:06,919 So args=self.reqparse .parse_args, 74 00:05:06,919 --> 00:05:11,651 I dare you to say that line like five times fast. 75 00:05:11,651 --> 00:05:14,634 And we're gonna return jsonify, you know what, we're gonna return. 76 00:05:17,685 --> 00:05:20,710 We're gonna return nothing. 77 00:05:20,710 --> 00:05:23,860 Okay, so we get the same response back on get or post but 78 00:05:23,860 --> 00:05:25,790 on post it parses these args. 79 00:05:25,790 --> 00:05:27,040 All right, so now, 80 00:05:27,040 --> 00:05:31,920 I should be able to post it because the method's allowed now, I should have it. 81 00:05:31,920 --> 00:05:37,210 So let's hit send and no course title provided, that's right, 82 00:05:37,210 --> 00:05:39,710 I didn't provide a course title. 83 00:05:39,710 --> 00:05:43,870 And if you look here, you can see the status is a 400 bad request. 84 00:05:43,870 --> 00:05:46,700 So good, that's what i should get because it is a bad request, 85 00:05:46,700 --> 00:05:48,550 it doesn't have all of the right data. 86 00:05:49,610 --> 00:05:54,800 All right so let's come over to body and let's say raw and 87 00:05:54,800 --> 00:05:59,750 then we're going to put in title is Python Collections. 88 00:05:59,750 --> 00:06:03,020 Okay, so we're just gonna send that, that's all we're gonna send. 89 00:06:04,220 --> 00:06:06,990 Can I change, yeah. 90 00:06:06,990 --> 00:06:09,770 So JSON application JSON, okay, so send. 91 00:06:11,300 --> 00:06:17,510 And what did I get here, I got No course URL provided, 92 00:06:17,510 --> 00:06:20,160 which is also true, I did not provide a URL. 93 00:06:20,160 --> 00:06:23,780 All right, now, let's say URL and 94 00:06:23,780 --> 00:06:29,640 i'm just gonna send python-collections because I'm just playing with this, 95 00:06:29,640 --> 00:06:30,270 I don't know what I'm doing. 96 00:06:30,270 --> 00:06:34,960 Let's send that, and I get back the data. 97 00:06:36,320 --> 00:06:41,060 Wow, okay, so I got back a 200, 98 00:06:41,060 --> 00:06:43,520 everything's okay, and I got back the data. 99 00:06:43,520 --> 00:06:47,360 This isn't what I wanted to get though, because python-collections, 100 00:06:47,360 --> 00:06:49,420 right here, that's not a valid URL. 101 00:06:50,710 --> 00:06:52,498 So we need to make the parsers smarter. 102 00:06:52,498 --> 00:06:56,296 Okay flask REST will come with a bunch of predefined inputs, 103 00:06:56,296 --> 00:07:00,479 you can make your own but you often probably don't have to though. 104 00:07:00,479 --> 00:07:03,584 The one that I need is included, so I'm going to use it. 105 00:07:03,584 --> 00:07:09,253 So I'm gonna come up here to reqparse and I'm also import inputs, 106 00:07:09,253 --> 00:07:13,440 going to have a lot of imports here from restful. 107 00:07:13,440 --> 00:07:16,700 So, now title here by default these are always strings so 108 00:07:16,700 --> 00:07:18,230 I don't need to add anything there. 109 00:07:18,230 --> 00:07:23,687 So here on add argument, I'm going to add a new argument to the argument and I'm 110 00:07:23,687 --> 00:07:29,480 gonna be type and I am going to put the type is a URL and it comes from inputs. 111 00:07:30,610 --> 00:07:34,300 So now let's see what happens when I try to post a bad URL. 112 00:07:35,350 --> 00:07:40,900 So I hit send, and now I've got the 400, and the no course URL provided. 113 00:07:40,900 --> 00:07:44,120 Great, because that's true, I did not send a URL. 114 00:07:45,190 --> 00:07:48,660 All right, so now what if I send an actual valid URL? 115 00:07:48,660 --> 00:07:55,328 Let's come back over here https://teamtreehouse.com/library/python-- 116 00:07:55,328 --> 00:07:56,700 collections. 117 00:07:56,700 --> 00:07:58,890 All right, so send that. 118 00:07:58,890 --> 00:08:01,190 I have 200 and I got back my courses list. 119 00:08:02,340 --> 00:08:04,320 So cool, that's the 200 that I expected. 120 00:08:05,320 --> 00:08:08,740 I want to add one more part, I wanna actually save the model instance. 121 00:08:08,740 --> 00:08:10,230 I'm not going to about changing the output though. 122 00:08:11,360 --> 00:08:13,590 Because that's just a lot of trouble for right now and 123 00:08:13,590 --> 00:08:15,100 we'll deal with that in a minute. 124 00:08:15,100 --> 00:08:18,540 So I've got models imported already, so that's cool. 125 00:08:18,540 --> 00:08:21,270 So then down here once I parse the args, 126 00:08:21,270 --> 00:08:25,860 the args basically become a dictionary of all these items. 127 00:08:25,860 --> 00:08:31,830 So I'm gonna do is I'm gonna do models.Course.create(**args). 128 00:08:31,830 --> 00:08:38,692 And that will take the args dictionary and feed all of that data into Course.create. 129 00:08:38,692 --> 00:08:43,620 So, cool, and now, if I go and submit my thing again, 130 00:08:44,770 --> 00:08:49,350 still got a 200 and I don't have a way to look at this yet. 131 00:08:49,350 --> 00:08:51,920 We'll check out the data that's in the database, in the next video. 132 00:08:53,010 --> 00:08:53,760 For now though, 133 00:08:53,760 --> 00:08:57,500 I'm gonna add the rest of these request parsers, while you do a code challenge. 134 00:08:57,500 --> 00:09:01,230 You should try and do the requests parsers yourself too, to both course, 135 00:09:01,230 --> 00:09:04,150 singular, and to review list and review. 136 00:09:04,150 --> 00:09:06,445 And in the next video you can compare yours to mine. 137 00:09:06,445 --> 00:09:11,640 Reqparse handles the request part of the request response cycle, 138 00:09:11,640 --> 00:09:13,590 we still need to deal with the response half. 139 00:09:13,590 --> 00:09:14,590 We'll do that in the next video.