WEBVTT 1 00:00:00.230 --> 00:00:01.480 Hi, welcome back. 2 00:00:01.480 --> 00:00:03.490 In this video, we will be turning our project 3 00:00:03.490 --> 00:00:05.360 which used an in-memory database 4 00:00:05.360 --> 00:00:08.300 into one using files for storage. 5 00:00:08.300 --> 00:00:11.660 What we've got here is our database which is a list. 6 00:00:11.660 --> 00:00:13.120 So, the first thing to do 7 00:00:13.120 --> 00:00:16.560 is to start transitioning our database.py file 8 00:00:16.560 --> 00:00:18.710 from using this list to store things 9 00:00:18.710 --> 00:00:20.173 into using a file. 10 00:00:21.680 --> 00:00:22.520 This is the reason 11 00:00:22.520 --> 00:00:24.290 why I've structure the code the way 12 00:00:24.290 --> 00:00:25.890 that I've structured it for you. 13 00:00:26.880 --> 00:00:28.670 Now If we want to add a book, 14 00:00:28.670 --> 00:00:32.110 we already know how to add a new line to a database, 15 00:00:32.110 --> 00:00:34.660 or if we don't, we're going to learn in this video. 16 00:00:35.570 --> 00:00:37.640 We already know how to read a file, 17 00:00:37.640 --> 00:00:38.950 and get all it's contents. 18 00:00:38.950 --> 00:00:42.550 We already know how to save into a file. 19 00:00:42.550 --> 00:00:44.500 We already how to read a file, 20 00:00:44.500 --> 00:00:46.700 and delete something and then save it again. 21 00:00:48.080 --> 00:00:50.933 So, this database.py here, 22 00:00:52.420 --> 00:00:55.100 is what's called an interface in programming. 23 00:00:55.100 --> 00:00:58.290 An interface between our business logic, 24 00:00:58.290 --> 00:01:02.430 what a programme is supposed to do, and the storage 25 00:01:02.430 --> 00:01:05.720 which in this case would be a database, sorry a file, 26 00:01:05.720 --> 00:01:08.570 and we're going to move on to database soon. 27 00:01:08.570 --> 00:01:11.370 So, if we wanted to add book, 28 00:01:11.370 --> 00:01:14.300 that would be very straight forward. 29 00:01:14.300 --> 00:01:17.420 All we have to do is, well first of all 30 00:01:17.420 --> 00:01:19.720 before we actually start writing any code, 31 00:01:19.720 --> 00:01:21.683 let's change this to a CSV file, 32 00:01:22.820 --> 00:01:25.260 and decide on the format of the CSV file 33 00:01:26.440 --> 00:01:31.363 which I think should be named "author, read", like so. 34 00:01:32.520 --> 00:01:35.030 Now that that's clear, we have decided that we're going 35 00:01:35.030 --> 00:01:37.300 to store "name" then "author" then "read" 36 00:01:37.300 --> 00:01:40.910 separated by commas, we can continue. 37 00:01:40.910 --> 00:01:42.600 Notice that it could be beneficial 38 00:01:42.600 --> 00:01:44.960 to separate it by hashes instead, 39 00:01:44.960 --> 00:01:48.370 because the titles may have commas in them, 40 00:01:48.370 --> 00:01:50.040 but for now we're not going to worry about that 41 00:01:50.040 --> 00:01:52.383 you can make that change later on if you want. 42 00:01:53.610 --> 00:01:58.027 So, to add a book, all we have to do is say 43 00:01:58.027 --> 00:02:03.027 "with open books.txt" in "read mode as file", 44 00:02:05.560 --> 00:02:09.520 and here, sorry "Write mode as file", 45 00:02:09.520 --> 00:02:11.210 and here what we are going to do 46 00:02:11.210 --> 00:02:13.590 is add a new book at the end, 47 00:02:13.590 --> 00:02:15.640 I'm just going to delete this thing here. 48 00:02:17.020 --> 00:02:19.090 However, I mentioned earlier on 49 00:02:19.090 --> 00:02:20.600 when we started looking at files, 50 00:02:20.600 --> 00:02:24.820 that "Write mode" would erase all contents of the file, 51 00:02:24.820 --> 00:02:26.870 and then you would be able to start writing 52 00:02:26.870 --> 00:02:28.960 from the very top the file. 53 00:02:28.960 --> 00:02:31.660 We don't want to do this because our "add_book" 54 00:02:31.660 --> 00:02:34.960 should add a new book probably at the end of the file. 55 00:02:34.960 --> 00:02:36.133 We do want to keep the other books 56 00:02:36.133 --> 00:02:37.740 that are already in the file, 57 00:02:37.740 --> 00:02:38.910 otherwise we would only ever be able 58 00:02:38.910 --> 00:02:40.930 to have one book at a time. 59 00:02:40.930 --> 00:02:43.640 Instead of "w mode", we can use "a mode" 60 00:02:43.640 --> 00:02:45.290 which stands for append. 61 00:02:45.290 --> 00:02:47.510 So, anything we write will automatically go 62 00:02:47.510 --> 00:02:49.023 to the very end of the file. 63 00:02:50.870 --> 00:02:53.340 Because our file is going to have this structure, 64 00:02:53.340 --> 00:02:56.290 and then it's going to have a "\n" at the end, 65 00:02:56.290 --> 00:02:58.930 anything we write is always going to be 66 00:02:58.930 --> 00:03:00.940 at the very bottom of the file. 67 00:03:00.940 --> 00:03:03.320 Here's why, we're going to add a book, 68 00:03:03.320 --> 00:03:04.630 and that's going to be in this format, 69 00:03:04.630 --> 00:03:06.463 name, author, read, new line. 70 00:03:07.610 --> 00:03:08.920 Then we'll add another one, 71 00:03:08.920 --> 00:03:12.533 and because there's a new line it will go on the next line. 72 00:03:13.900 --> 00:03:16.400 Then when we add another one it'll go on the next line, 73 00:03:16.400 --> 00:03:17.660 and so forth. 74 00:03:17.660 --> 00:03:19.930 So, it's important that we include that new line there, 75 00:03:19.930 --> 00:03:21.700 because append mode will just go 76 00:03:21.700 --> 00:03:24.420 to the very end of the file, the very last character, 77 00:03:24.420 --> 00:03:25.670 which will be a new line. 78 00:03:28.080 --> 00:03:33.080 So, all we have to do is "file.write name author", 79 00:03:37.890 --> 00:03:39.610 and then we have to decide on how we are going 80 00:03:39.610 --> 00:03:41.273 to store false values. 81 00:03:42.550 --> 00:03:45.160 Because the text file we are going to be using 82 00:03:45.160 --> 00:03:50.160 is not a python file, maybe "false" doesn't make much sense, 83 00:03:50.260 --> 00:03:52.520 although it could, it's up to you, 84 00:03:52.520 --> 00:03:54.810 but I'm going to store it as a zero, 85 00:03:54.810 --> 00:03:57.320 zero for false, one for true, 86 00:03:57.320 --> 00:03:58.670 it's up to you what you do. 87 00:04:00.227 --> 00:04:03.107 And this is how we add a new book to "books.txt". 88 00:04:04.330 --> 00:04:07.180 Notice though we still got our books variable up here. 89 00:04:07.180 --> 00:04:09.150 We don't need that so, I'm going to rename it 90 00:04:09.150 --> 00:04:13.940 into "books file" and this is going to be books.txt, 91 00:04:13.940 --> 00:04:16.320 and this is going to be "books file". 92 00:04:16.320 --> 00:04:19.750 That way, we're storing the file name up here, 93 00:04:19.750 --> 00:04:21.350 that's essentially our database. 94 00:04:24.070 --> 00:04:27.000 To get all books is going to be slightly more challenging. 95 00:04:27.000 --> 00:04:28.150 Once again, I'm going to go here, 96 00:04:28.150 --> 00:04:31.270 and have a couple of lines of "name, author, read", 97 00:04:31.270 --> 00:04:34.290 just so it's a bit clearer what we're doing. 98 00:04:34.290 --> 00:04:35.940 And the first thing we want to do is, 99 00:04:35.940 --> 00:04:37.530 of course, open the file. 100 00:04:37.530 --> 00:04:38.680 You know how to do this 101 00:04:40.050 --> 00:04:43.430 with "open books file" and "read mode as file", 102 00:04:43.430 --> 00:04:45.860 and now we want to get all the lines, 103 00:04:45.860 --> 00:04:49.120 but we want to get the lines without the white space. 104 00:04:49.120 --> 00:04:52.180 I hope you remember how to do this exactly, 105 00:04:52.180 --> 00:04:54.093 using the strip method. 106 00:04:57.530 --> 00:04:59.317 We are going to say lines is 107 00:04:59.317 --> 00:05:03.767 "line.strip for line in file.readlines", 108 00:05:05.040 --> 00:05:06.740 that's gonna read all the lines, 109 00:05:06.740 --> 00:05:08.680 including the backslash n's, 110 00:05:08.680 --> 00:05:12.860 and that's going to give us each one in a list, 111 00:05:12.860 --> 00:05:14.270 in the element of the list, 112 00:05:14.270 --> 00:05:15.770 and for each of the elements, 113 00:05:15.770 --> 00:05:17.790 we're going to strip the white space 114 00:05:17.790 --> 00:05:20.533 which is going to remove this here. 115 00:05:22.490 --> 00:05:26.720 So, now we're going to have this as our contents 116 00:05:26.720 --> 00:05:27.853 of this list here. 117 00:05:29.310 --> 00:05:31.470 Now, we can also chain to it... 118 00:05:33.660 --> 00:05:35.400 A split, 119 00:05:35.400 --> 00:05:37.650 so that we will get... 120 00:05:37.650 --> 00:05:42.650 one list... of lists. 121 00:05:43.110 --> 00:05:46.110 Indeed, now our list will have this format... 122 00:05:53.680 --> 00:05:56.640 Like so, so we'll have one list, 123 00:05:56.640 --> 00:06:00.000 and inside it we'll have the sub list 124 00:06:00.000 --> 00:06:01.600 where each one is going to be a list 125 00:06:01.600 --> 00:06:03.367 of "name, author, read". 126 00:06:07.740 --> 00:06:08.573 Now what we're going to do 127 00:06:08.573 --> 00:06:11.343 is we're going to construct our book dictionaries. 128 00:06:13.640 --> 00:06:16.283 So, this is going to be another list comprehension. 129 00:06:17.650 --> 00:06:18.960 In the list, and notice by the way 130 00:06:18.960 --> 00:06:20.750 you can put list comprehensions in multiple lines, 131 00:06:20.750 --> 00:06:22.350 it's totally cool, totally fine. 132 00:06:24.130 --> 00:06:26.077 Line 0... 133 00:06:26.077 --> 00:06:28.360 "author" is going to be line one 134 00:06:28.360 --> 00:06:30.483 and "read" is going to be line 2. 135 00:06:31.720 --> 00:06:33.070 Of course, line doesn't exist 136 00:06:33.070 --> 00:06:35.940 so, we're going to do "for line in lines", 137 00:06:35.940 --> 00:06:36.990 and there we have it. 138 00:06:37.890 --> 00:06:40.390 Remember, that each line, 139 00:06:40.390 --> 00:06:42.490 or rather the whole lines list 140 00:06:42.490 --> 00:06:45.377 has this format "name, author, and read", 141 00:06:46.527 --> 00:06:49.690 "name, author, read" 142 00:06:49.690 --> 00:06:52.993 So, "for line in lines" has given us one of these lists, 143 00:06:53.830 --> 00:06:55.010 and then we're saying that "name" 144 00:06:55.010 --> 00:06:58.157 is the zeroth element of this sub list which is a name, 145 00:06:58.157 --> 00:07:00.090 "author" is the first element of this sub list 146 00:07:00.090 --> 00:07:01.137 which is the author, 147 00:07:01.137 --> 00:07:03.670 "read" is the third element of this sub list 148 00:07:03.670 --> 00:07:06.610 which is the read status they have. 149 00:07:08.200 --> 00:07:09.450 Then we can return books, 150 00:07:10.310 --> 00:07:12.050 or indeed, if you want to save some space 151 00:07:12.050 --> 00:07:13.890 because this variable here... 152 00:07:17.402 --> 00:07:19.000 Is pretty redundant 153 00:07:19.000 --> 00:07:22.870 we can just say return this list comprehension. 154 00:07:22.870 --> 00:07:24.860 That's gonna execute the list comprehension first, 155 00:07:24.860 --> 00:07:25.853 and then return it. 156 00:07:30.100 --> 00:07:31.840 Okay, we got the get all books, 157 00:07:31.840 --> 00:07:33.410 and the add book 158 00:07:33.410 --> 00:07:36.913 now, we can move on to marking a book as read. 159 00:07:36.913 --> 00:07:38.430 This not so easy 160 00:07:39.360 --> 00:07:41.540 because although it's possible to go 161 00:07:41.540 --> 00:07:43.940 into the file and modify it, 162 00:07:43.940 --> 00:07:46.623 it's actually much easier to read the file in, 163 00:07:47.720 --> 00:07:49.810 Modify the book that we want, 164 00:07:49.810 --> 00:07:52.690 and then save them all to the file again. 165 00:07:52.690 --> 00:07:54.840 That's actually much easier, 166 00:07:54.840 --> 00:07:57.040 so we're going to go for that in this video. 167 00:07:58.290 --> 00:07:59.300 The first thing to do is, 168 00:07:59.300 --> 00:08:03.253 of course, to say "books" is "get all books"... 169 00:08:04.843 --> 00:08:05.676 Okay. 170 00:08:10.210 --> 00:08:11.770 For some reason it keeps saying... 171 00:08:11.770 --> 00:08:14.050 Oh yeah, this thing here. 172 00:08:14.050 --> 00:08:16.130 It kept saying this shadow is on the outer variable, 173 00:08:16.130 --> 00:08:18.360 but I was pretty sure we deleted it, 174 00:08:18.360 --> 00:08:20.040 so I was wondering what the hell that was. 175 00:08:20.040 --> 00:08:22.510 But of course, the global books there was creating it again, 176 00:08:22.510 --> 00:08:24.210 so we don't want to do that. 177 00:08:24.210 --> 00:08:25.570 Anyway, marking book as read, 178 00:08:25.570 --> 00:08:28.043 the first thing we want to do is get all the books, 179 00:08:29.040 --> 00:08:30.740 then we want to iterate over them, 180 00:08:33.260 --> 00:08:35.800 and well in fact, we already have it here. 181 00:08:35.800 --> 00:08:36.633 For booking books, 182 00:08:36.633 --> 00:08:39.270 if the books name is equal to the name that we passed in, 183 00:08:39.270 --> 00:08:42.660 we're going to set it to read except now instead of true, 184 00:08:42.660 --> 00:08:44.210 it's going to be one 185 00:08:44.210 --> 00:08:47.513 because one means true and zero means false in our file, 186 00:08:48.570 --> 00:08:49.610 and then at the end 187 00:08:49.610 --> 00:08:52.720 we have to save all of the books that we've retrieved 188 00:08:52.720 --> 00:08:54.130 back into the database, 189 00:08:54.130 --> 00:08:57.793 and one of will have changed from zero to one. 190 00:08:58.960 --> 00:09:00.920 So, for that I'm going to create another function 191 00:09:00.920 --> 00:09:04.040 that I'm going to call "_save all books", 192 00:09:04.040 --> 00:09:06.010 and I'm going to pass it the books that we read, 193 00:09:06.010 --> 00:09:06.960 the books variable. 194 00:09:07.850 --> 00:09:10.350 This function doesn't exist so we shall create it. 195 00:09:13.310 --> 00:09:16.660 The reason why I'm calling it "_save all books" is 196 00:09:16.660 --> 00:09:19.310 because in Python this tells other developers, 197 00:09:19.310 --> 00:09:22.120 that they should not call this function. 198 00:09:22.120 --> 00:09:25.940 You should only call this function from within this file. 199 00:09:25.940 --> 00:09:29.594 This is normally known as a private function 200 00:09:29.594 --> 00:09:32.000 in most programming languages. 201 00:09:32.000 --> 00:09:34.500 Python doesn't have the concept of a private function, 202 00:09:34.500 --> 00:09:36.100 so, other people form outside of the file 203 00:09:36.100 --> 00:09:38.440 can still call this function if they want, 204 00:09:38.440 --> 00:09:40.490 but the naming conventions in Python says that 205 00:09:40.490 --> 00:09:42.600 if a function has a underscore in front, 206 00:09:42.600 --> 00:09:44.200 you should probably not call it. 207 00:09:45.670 --> 00:09:47.670 So, that's what we're doing here just calling it 208 00:09:47.670 --> 00:09:50.790 with underscore first or naming it with an underscore first 209 00:09:50.790 --> 00:09:51.930 so that other people know that 210 00:09:51.930 --> 00:09:54.210 this is a function they probably shouldn't use, 211 00:09:54.210 --> 00:09:56.977 they should only use "delete book", "mark book as read", 212 00:09:56.977 --> 00:09:58.927 "get all books", and "add book". 213 00:10:00.350 --> 00:10:02.360 So, in order to save all the books 214 00:10:02.360 --> 00:10:04.190 well, we just have to open the file 215 00:10:05.920 --> 00:10:07.300 in write mode this time, 216 00:10:07.300 --> 00:10:08.800 and we're going to delete the entire file, 217 00:10:08.800 --> 00:10:10.033 and rewrite it, 218 00:10:13.473 --> 00:10:14.570 and we're going to go through each book, 219 00:10:14.570 --> 00:10:16.067 and say "file write", 220 00:10:17.907 --> 00:10:18.847 "book name", 221 00:10:21.757 --> 00:10:22.767 "book author", 222 00:10:25.060 --> 00:10:26.737 and "book read", 223 00:10:28.070 --> 00:10:30.550 and at the end make sure to put the "/n" 224 00:10:30.550 --> 00:10:32.850 that's pretty important as well. 225 00:10:32.850 --> 00:10:35.240 Actually, I think we forgot to put it up here. 226 00:10:35.240 --> 00:10:38.630 So, make sure to "file write", "/n" in there as well, 227 00:10:38.630 --> 00:10:40.030 that's important. 228 00:10:40.030 --> 00:10:41.013 I did say earlier it was really important 229 00:10:41.013 --> 00:10:42.610 then I forgot. 230 00:10:42.610 --> 00:10:43.443 There you have it, 231 00:10:43.443 --> 00:10:45.390 so now, what we're doing in this function 232 00:10:45.390 --> 00:10:47.480 is opening the file deleting all its contents 233 00:10:47.480 --> 00:10:50.410 with the write mode, and then going through all of the books 234 00:10:50.410 --> 00:10:53.320 in the list that we got as a parameter, 235 00:10:53.320 --> 00:10:56.950 and for each book writing out it's details in csv format, 236 00:10:56.950 --> 00:10:58.090 and a new line at the end, 237 00:10:58.090 --> 00:11:00.780 so it's just going to re write our entire file. 238 00:11:00.780 --> 00:11:02.480 Not the most efficient thing to be doing, 239 00:11:02.480 --> 00:11:03.770 I'll be honest with you, 240 00:11:03.770 --> 00:11:06.603 but it's much easier than going and modifying the file. 241 00:11:09.300 --> 00:11:13.470 Okay, so now this "_save all books" function does exist, 242 00:11:13.470 --> 00:11:15.270 so we're safe to use it there, 243 00:11:15.270 --> 00:11:16.780 and again what we have done in this function 244 00:11:16.780 --> 00:11:18.130 is read all the books, 245 00:11:18.130 --> 00:11:20.450 going through them and modifying the one we want, 246 00:11:20.450 --> 00:11:22.473 and then saved them all back, 247 00:11:23.465 --> 00:11:24.690 and that is essentially the same thing we're 248 00:11:24.690 --> 00:11:26.697 going to do for deleting a book. 249 00:11:26.697 --> 00:11:28.010 So, I encourage you to, 250 00:11:28.010 --> 00:11:30.430 now that I've implemented these two functions, 251 00:11:30.430 --> 00:11:33.610 go and implement the delete book function on your own. 252 00:11:33.610 --> 00:11:35.990 Once again, read all the books, 253 00:11:35.990 --> 00:11:39.160 recreate the list without the book you want to delete, 254 00:11:39.160 --> 00:11:41.280 and then save them all back. 255 00:11:41.280 --> 00:11:42.113 Let's try that. 256 00:11:47.010 --> 00:11:48.030 I hope you managed, 257 00:11:48.030 --> 00:11:49.397 what I would do is once again say 258 00:11:49.397 --> 00:11:51.960 "books" is "get all books". 259 00:11:51.960 --> 00:11:53.767 Now, I'm going to say that books is actually 260 00:11:53.767 --> 00:11:56.770 "book for book in books if" the book's name 261 00:11:57.700 --> 00:12:00.760 is not equal to the name we got as a parameter 262 00:12:00.760 --> 00:12:03.463 and finally save all books. 263 00:12:05.800 --> 00:12:07.440 Notice how the function call here, 264 00:12:07.440 --> 00:12:09.780 this function is above this function, 265 00:12:09.780 --> 00:12:12.910 and I did say previously that you want functions 266 00:12:12.910 --> 00:12:15.170 to be defined in the order in which they are used, 267 00:12:15.170 --> 00:12:18.273 this is fine because this function was actually used above. 268 00:12:19.110 --> 00:12:21.253 So, I think this is okay. 269 00:12:22.210 --> 00:12:24.410 Again, we're using the list comprehension 270 00:12:24.410 --> 00:12:27.210 to iterate over our books, 271 00:12:27.210 --> 00:12:30.240 and then only put the book into a new list 272 00:12:30.240 --> 00:12:32.840 if the book name matches 273 00:12:32.840 --> 00:12:33.820 sorry, doesn't match. 274 00:12:33.820 --> 00:12:35.080 So we're putting in all the books 275 00:12:35.080 --> 00:12:37.303 except the one that is here, 276 00:12:39.130 --> 00:12:40.090 and that's it. 277 00:12:40.090 --> 00:12:43.107 We now have our "delete book", "mark book as read", 278 00:12:43.107 --> 00:12:45.100 "get all books", and "add book" functions, 279 00:12:45.100 --> 00:12:48.270 they are still the same functions as before, 280 00:12:48.270 --> 00:12:49.740 the names are the same. 281 00:12:49.740 --> 00:12:53.730 All they're doing now is they are storing things into a file 282 00:12:53.730 --> 00:12:55.570 instead of into a list. 283 00:12:55.570 --> 00:12:57.880 So, if we go over to app.py... 284 00:13:00.480 --> 00:13:02.760 We actually don't have to change anything 285 00:13:02.760 --> 00:13:06.090 because "database.add book" doesn't know 286 00:13:06.090 --> 00:13:08.880 whether this is going into a list or a file, 287 00:13:08.880 --> 00:13:09.920 and it doesn't care. 288 00:13:09.920 --> 00:13:12.690 All it knows is that the book is being added. 289 00:13:12.690 --> 00:13:15.593 Here in list books, "database.get all books" 290 00:13:15.593 --> 00:13:16.840 will get the books, 291 00:13:16.840 --> 00:13:19.320 you don't care where it's getting them from. 292 00:13:19.320 --> 00:13:23.660 So, we have very well, decoupled our business logic, 293 00:13:23.660 --> 00:13:26.200 our app from our database. 294 00:13:26.200 --> 00:13:28.050 We have not done a perfect job 295 00:13:28.050 --> 00:13:31.060 because the "book read" status is now going to be 296 00:13:33.440 --> 00:13:35.490 Yes if the book is... 297 00:13:36.720 --> 00:13:40.870 exactly equal to one otherwise no. 298 00:13:40.870 --> 00:13:43.770 So, now instead of being true or false it's one or zero, 299 00:13:43.770 --> 00:13:45.803 so that's the only thing there. 300 00:13:47.760 --> 00:13:48.627 Okay, other than that, 301 00:13:48.627 --> 00:13:50.530 "prompt read book" is going to get the name, 302 00:13:50.530 --> 00:13:51.860 and then mark it as read, 303 00:13:51.860 --> 00:13:54.100 and you know that in the background the database is going 304 00:13:54.100 --> 00:13:56.240 to the file, opening it, looking through all the books, 305 00:13:56.240 --> 00:13:58.680 marking one as read, saving them back, 306 00:13:58.680 --> 00:14:00.323 but your app doesn't care. 307 00:14:01.354 --> 00:14:03.770 So, what we have created here is a nice interface 308 00:14:03.770 --> 00:14:07.890 between our app and our data storage mechanism, 309 00:14:07.890 --> 00:14:10.050 that very nicely hides 310 00:14:10.050 --> 00:14:13.730 all the complexity inside this file, 311 00:14:13.730 --> 00:14:16.610 and this is as I said earlier normally called an interface, 312 00:14:16.610 --> 00:14:19.600 and the interface here is to our database, 313 00:14:19.600 --> 00:14:23.290 and the contents of the interface are these four functions. 314 00:14:23.290 --> 00:14:25.147 The "add book", "get all books", 315 00:14:25.147 --> 00:14:28.230 "mark book as read", and "delete book", 316 00:14:28.230 --> 00:14:31.040 and normally we've been talking about user interfaces 317 00:14:31.040 --> 00:14:33.500 because users have been interacting 318 00:14:33.500 --> 00:14:35.963 with the menu that we've given them, 319 00:14:36.820 --> 00:14:40.100 but this database is an API, 320 00:14:40.100 --> 00:14:41.830 it's an application programing interface. 321 00:14:41.830 --> 00:14:45.650 We've created an interface so that this part of the programme, 322 00:14:45.650 --> 00:14:48.720 app.py, can interact with another part of the programme, 323 00:14:48.720 --> 00:14:52.357 the database, via the interface that we've defined, 324 00:14:52.357 --> 00:14:53.687 "prompt add book", "list books", 325 00:14:53.687 --> 00:14:56.290 "prompt read book", and "prompt delete book". 326 00:14:56.290 --> 00:14:59.110 So, if you think of app.py as a user, 327 00:14:59.110 --> 00:15:01.830 these are the option that it can use 328 00:15:01.830 --> 00:15:03.640 to interact with a database, 329 00:15:03.640 --> 00:15:06.780 and it doesn't care what the implementation is, 330 00:15:06.780 --> 00:15:10.020 whether it's a list or whether it's a file, 331 00:15:10.020 --> 00:15:11.530 and indeed as we move forward 332 00:15:11.530 --> 00:15:15.040 into databases as a sequel database, 333 00:15:15.040 --> 00:15:18.490 as a relational database, it won't care either about that. 334 00:15:18.490 --> 00:15:20.893 Let's run this app and try it out. 335 00:15:22.530 --> 00:15:23.860 And by the way, I'm just going to stop that, 336 00:15:23.860 --> 00:15:25.480 and this is annoying me a little bit, 337 00:15:25.480 --> 00:15:27.180 we are going to add a space there. 338 00:15:28.050 --> 00:15:29.570 Okay, let's run it. 339 00:15:29.570 --> 00:15:30.800 We're going to add a new book, 340 00:15:30.800 --> 00:15:34.930 we're going to enter "Clean Code" by Robert, 341 00:15:34.930 --> 00:15:37.010 and as you can see no errors. 342 00:15:37.010 --> 00:15:39.450 We're going to list all the books, 343 00:15:39.450 --> 00:15:41.150 and we see "Clean Code" by Robert. 344 00:15:42.020 --> 00:15:44.020 We can mark a book as read, 345 00:15:44.020 --> 00:15:45.480 and that'll be "Clean Code", 346 00:15:45.480 --> 00:15:47.320 then we can list them again, 347 00:15:47.320 --> 00:15:49.770 and now it appears as read, we can delete a book, 348 00:15:51.680 --> 00:15:54.670 and we can list them again, and nothing appears there, 349 00:15:54.670 --> 00:15:58.073 and notice how books.txt has not appeared in PyCharm yet. 350 00:15:59.030 --> 00:16:00.680 The file does exist, 351 00:16:00.680 --> 00:16:05.110 if you go on your finder or on your window explorer programme, 352 00:16:05.110 --> 00:16:07.580 into the directory in which this project is, 353 00:16:07.580 --> 00:16:08.413 you will see the file is there, 354 00:16:08.413 --> 00:16:10.650 but PyCharm doesn't quite update that quickly, 355 00:16:10.650 --> 00:16:12.100 so it's not showing it there. 356 00:16:13.750 --> 00:16:15.990 Okay, let's exit that programme, 357 00:16:15.990 --> 00:16:17.520 notice how now the file is up here, 358 00:16:17.520 --> 00:16:18.963 and let's delete the file. 359 00:16:21.650 --> 00:16:23.920 Now, let's run the app again, 360 00:16:23.920 --> 00:16:26.080 and now I'm going to read books. 361 00:16:26.080 --> 00:16:29.093 What do you think is going to happen when I press Enter? 362 00:16:31.330 --> 00:16:32.303 Well, let's see. 363 00:16:33.900 --> 00:16:36.000 Oops, probably not what we wanted. 364 00:16:36.000 --> 00:16:38.490 We probably wanted either nothing to print out, 365 00:16:38.490 --> 00:16:40.820 or even nicer would be some sort of message saying 366 00:16:40.820 --> 00:16:42.270 you don't have any books, 367 00:16:42.270 --> 00:16:44.770 but instead we got a file not found error, 368 00:16:44.770 --> 00:16:47.087 no such file directory "books.txt", 369 00:16:48.250 --> 00:16:49.290 and the reason for that, 370 00:16:49.290 --> 00:16:50.810 I'm just going to hide this away. 371 00:16:50.810 --> 00:16:55.810 The reason for that is because when we add a new book, 372 00:16:56.950 --> 00:16:58.720 or indeed, when we save all books, 373 00:16:58.720 --> 00:17:03.150 we are using a constructive method of file opening. 374 00:17:03.150 --> 00:17:05.330 So, we are crating the file here, 375 00:17:05.330 --> 00:17:08.720 or we are creating the file here if it doesn't exist, 376 00:17:08.720 --> 00:17:11.960 but the read method is not constructive, 377 00:17:11.960 --> 00:17:14.920 it is more passive and it doesn't create the file 378 00:17:14.920 --> 00:17:16.040 if it doesn't exists, 379 00:17:16.040 --> 00:17:19.390 indeed, it gives you an error and it says file not found. 380 00:17:19.390 --> 00:17:21.910 So, what we want to do is make sure the file exists 381 00:17:21.910 --> 00:17:25.480 before we go and read it, 382 00:17:25.480 --> 00:17:28.760 and for that I'm going to create one last function here 383 00:17:28.760 --> 00:17:31.480 in our database interface, 384 00:17:31.480 --> 00:17:32.693 and that's going to be, 385 00:17:35.497 --> 00:17:37.380 "create book table" 386 00:17:37.380 --> 00:17:39.730 and I'm consciously calling it "table" 387 00:17:39.730 --> 00:17:41.330 even though it's a file 388 00:17:41.330 --> 00:17:42.907 because this is called database, 389 00:17:42.907 --> 00:17:44.670 and not called files, 390 00:17:44.670 --> 00:17:47.240 and as we migrate over into a database, 391 00:17:47.240 --> 00:17:48.320 this is going to be responsible 392 00:17:48.320 --> 00:17:51.340 for creating the table that is going to store the books. 393 00:17:51.340 --> 00:17:52.930 If you don't know what I'm talking about don't worry, 394 00:17:52.930 --> 00:17:54.730 we are going to get there very soon. 395 00:17:55.940 --> 00:17:59.770 So, all to do here is open it in write mode, 396 00:17:59.770 --> 00:18:01.323 and you don't have to do anything with it, 397 00:18:01.323 --> 00:18:02.810 It's going to close automatically 398 00:18:02.810 --> 00:18:05.230 when you exit the context manager, 399 00:18:05.230 --> 00:18:07.140 so you don't have to worry about anything, 400 00:18:07.140 --> 00:18:08.640 and indeed, "as file" is optional 401 00:18:08.640 --> 00:18:09.740 so you don't need it either 402 00:18:09.740 --> 00:18:12.580 because you aren't going to use the variable for anything, 403 00:18:12.580 --> 00:18:13.413 and again, 404 00:18:14.270 --> 00:18:17.403 this just to make sure the file is there. 405 00:18:18.950 --> 00:18:20.900 Okay, now we can rerun the app, 406 00:18:20.900 --> 00:18:22.230 list our books... 407 00:18:24.741 --> 00:18:26.280 Ah, of course my bad, 408 00:18:26.280 --> 00:18:29.140 we created the method here, the function in the interface, 409 00:18:29.140 --> 00:18:30.830 but we didn't actually call it. 410 00:18:30.830 --> 00:18:32.310 So, at the top of the menu 411 00:18:32.310 --> 00:18:34.540 before we ask the user for their input, 412 00:18:34.540 --> 00:18:38.260 just type "database.create book table", 413 00:18:38.260 --> 00:18:40.310 and that'll be all you need to do. 414 00:18:40.310 --> 00:18:43.253 Now, we can list books and we don't get anything back. 415 00:18:44.230 --> 00:18:47.360 Feel free, of course, to continue developing this programme, 416 00:18:47.360 --> 00:18:48.850 and as you stop, and when you stop it 417 00:18:48.850 --> 00:18:50.480 you get nice error there as well. 418 00:18:50.480 --> 00:18:52.420 Feel free to add some more stuff to your programme. 419 00:18:52.420 --> 00:18:53.830 What if there are no books? 420 00:18:53.830 --> 00:18:55.080 Print something else out. 421 00:18:56.400 --> 00:18:57.570 You know... 422 00:18:57.570 --> 00:19:00.210 Add some more data to the book store. 423 00:19:00.210 --> 00:19:01.810 You do whatever you want to do, 424 00:19:01.810 --> 00:19:03.440 this is your programme now so, 425 00:19:03.440 --> 00:19:06.083 congratulations on finishing this segment. 426 00:19:06.950 --> 00:19:08.480 As we move on, 427 00:19:08.480 --> 00:19:12.600 we're going to look at how to store this data as JSON, 428 00:19:12.600 --> 00:19:13.530 and if you're interested in that, 429 00:19:13.530 --> 00:19:14.980 just look at the next video. 430 00:19:14.980 --> 00:19:16.180 If you're not really keen 431 00:19:16.180 --> 00:19:19.210 on storing things in databases, in files any longer, 432 00:19:19.210 --> 00:19:20.720 feel free to skip the next video, 433 00:19:20.720 --> 00:19:22.940 move on the very following one, 434 00:19:22.940 --> 00:19:26.470 where we're going to start looking at databases. 435 00:19:26.470 --> 00:19:28.080 So, I'll see you either in the next video, 436 00:19:28.080 --> 00:19:29.300 or in the one after that. 437 00:19:29.300 --> 00:19:30.383 See you soon.