1 00:00:00,000 --> 00:00:15,760 2 00:00:15,760 --> 00:00:18,010 BRIAN YU: OK, welcome back everyone to Web Programming 3 00:00:18,010 --> 00:00:19,270 with Python and JavaScript. 4 00:00:19,270 --> 00:00:22,420 So in the past couple of weeks, we've been looking at HTML and CSS, 5 00:00:22,420 --> 00:00:26,500 learning about how we can write code that decides how our website ultimately 6 00:00:26,500 --> 00:00:28,850 looks by describing the structure of the code 7 00:00:28,850 --> 00:00:30,820 and by using CSS to describe the style the code 8 00:00:30,820 --> 00:00:32,762 to determine how our web page is styled. 9 00:00:32,762 --> 00:00:35,470 Today what we're going to do is we're going to take the next step 10 00:00:35,470 --> 00:00:38,410 and start building some dynamic web applications using a programming 11 00:00:38,410 --> 00:00:42,400 language called Python in order to build web applications that are a little more 12 00:00:42,400 --> 00:00:46,090 powerful than what we can have just by describing the contents of a web 13 00:00:46,090 --> 00:00:47,910 page using HTML, for instance. 14 00:00:47,910 --> 00:00:50,410 But before we can get the Flask, we should talk a little bit 15 00:00:50,410 --> 00:00:52,118 about the language that we're going to be 16 00:00:52,118 --> 00:00:54,160 using in order to create those web applications, 17 00:00:54,160 --> 00:00:55,660 and that language is Python. 18 00:00:55,660 --> 00:00:57,670 And so Python has come in a number of different versions. 19 00:00:57,670 --> 00:01:00,461 We're going to be in this class using the latest version of Python, 20 00:01:00,461 --> 00:01:04,030 as of now, which is Python 3.6. 21 00:01:04,030 --> 00:01:06,006 And so Python is a programming language that 22 00:01:06,006 --> 00:01:07,630 is an interpreted programming language. 23 00:01:07,630 --> 00:01:11,020 Meaning what we'll do is we'll be writing code in the Python programming 24 00:01:11,020 --> 00:01:11,680 language. 25 00:01:11,680 --> 00:01:13,471 And then we'll run it through what's called 26 00:01:13,471 --> 00:01:17,080 a Python interpreter, a program that reads in Python code line by line, 27 00:01:17,080 --> 00:01:20,590 and interprets it, tries to parse the Python, understand what it means, 28 00:01:20,590 --> 00:01:22,180 and then execute that code. 29 00:01:22,180 --> 00:01:25,210 And so what we'll do first before we dive into the web programming 30 00:01:25,210 --> 00:01:27,952 part of this is take a look at Python, just the language itself, 31 00:01:27,952 --> 00:01:30,910 get a feel for how the language works and what the different components 32 00:01:30,910 --> 00:01:32,380 and features of the language are. 33 00:01:32,380 --> 00:01:35,080 And after that, we'll use those skills using the tools 34 00:01:35,080 --> 00:01:38,770 that we can use in Python in order to use that language to generate 35 00:01:38,770 --> 00:01:41,300 dynamic web applications of our own. 36 00:01:41,300 --> 00:01:43,870 So let's dive right in and take a look at our first example 37 00:01:43,870 --> 00:01:45,610 of a program written in Python. 38 00:01:45,610 --> 00:01:48,130 And this program is Hello.py. 39 00:01:48,130 --> 00:01:51,310 The dot p-y extension is just a common extension 40 00:01:51,310 --> 00:01:55,070 for names of files that are files that contain Python code. 41 00:01:55,070 --> 00:01:58,300 So this piece of code is called Hello.py. 42 00:01:58,300 --> 00:01:59,890 And it's just got one line. 43 00:01:59,890 --> 00:02:03,370 And that line is a print, and then in parentheses and then 44 00:02:03,370 --> 00:02:05,930 in quotation marks, the words hello world. 45 00:02:05,930 --> 00:02:07,840 And so this is a very simple Python program. 46 00:02:07,840 --> 00:02:10,631 And let's try running this Python program just to see what happens. 47 00:02:10,631 --> 00:02:13,160 And then we'll take a look at how this is actually working. 48 00:02:13,160 --> 00:02:16,130 So in order to run a Python program on the command line, 49 00:02:16,130 --> 00:02:19,330 I'll type the word Python to run the Python interpreter, followed 50 00:02:19,330 --> 00:02:22,040 by the name of the Python file that I want to run. 51 00:02:22,040 --> 00:02:25,150 So in this case, the name of the Python file is hello dot py. 52 00:02:25,150 --> 00:02:30,040 And so if I type hello dot py and press Return, just to say run hello 53 00:02:30,040 --> 00:02:34,720 dot py in Python, what I get is just the words Hello World printed out 54 00:02:34,720 --> 00:02:36,290 to the terminal screen. 55 00:02:36,290 --> 00:02:37,506 And so that's all it does. 56 00:02:37,506 --> 00:02:39,880 A fairly simple program that just prints out hello world. 57 00:02:39,880 --> 00:02:41,624 And if we take a look at hello dot py, we 58 00:02:41,624 --> 00:02:43,540 can start to break down what's happening here. 59 00:02:43,540 --> 00:02:47,740 This word print, this is a function, just a word in Python 60 00:02:47,740 --> 00:02:52,120 that represents doing Something, In this case printing something to the screen. 61 00:02:52,120 --> 00:02:55,900 And inside the parentheses is what's called the function's argument, 62 00:02:55,900 --> 00:02:58,420 information we give to the print function, 63 00:02:58,420 --> 00:03:01,870 in this case telling the print function what it is that we want to print out. 64 00:03:01,870 --> 00:03:06,340 And so in this case, we have in the parentheses in the "string", which 65 00:03:06,340 --> 00:03:09,670 is just a sequence of text "hello world" meaning print out the words 66 00:03:09,670 --> 00:03:11,650 hello world to the screen, and therefore when 67 00:03:11,650 --> 00:03:14,620 we ran hello dot py by running Python, the result 68 00:03:14,620 --> 00:03:18,040 was that we got the words the hello world printed to the screen. 69 00:03:18,040 --> 00:03:21,879 And so that was a fairly straightforward Python program, 70 00:03:21,879 --> 00:03:24,170 just one line long that prints something to the screen. 71 00:03:24,170 --> 00:03:27,110 Let's take a look at something a little more sophisticated. 72 00:03:27,110 --> 00:03:31,030 So inside of a name dot py, now here I have 73 00:03:31,030 --> 00:03:33,044 a Python program that's got two lines. 74 00:03:33,044 --> 00:03:34,960 And so let's break down these lines one by one 75 00:03:34,960 --> 00:03:36,501 and get a sense for what's happening. 76 00:03:36,501 --> 00:03:40,450 Here line one, we define a name, where name is just 77 00:03:40,450 --> 00:03:43,660 a variable, some name that we're going to give it to a place 78 00:03:43,660 --> 00:03:47,320 where we can store data or information inside of our Python program. 79 00:03:47,320 --> 00:03:51,730 And name is going to be set equal to the result of this input function. 80 00:03:51,730 --> 00:03:55,090 And so input is a function that in Python asks the user 81 00:03:55,090 --> 00:03:56,830 to type in input at the command line. 82 00:03:56,830 --> 00:03:59,860 And when they press Return, whatever it is that they typed in, 83 00:03:59,860 --> 00:04:01,780 gets returned from the function. 84 00:04:01,780 --> 00:04:04,030 It's information that's passed back from the function. 85 00:04:04,030 --> 00:04:06,363 And if you're familiar with other programming languages, 86 00:04:06,363 --> 00:04:07,400 it's much the same idea. 87 00:04:07,400 --> 00:04:10,870 And so we ask the user to type in their name presumably. 88 00:04:10,870 --> 00:04:14,057 That gets stored inside of this variable called name. 89 00:04:14,057 --> 00:04:15,640 And now let's take a look at line two. 90 00:04:15,640 --> 00:04:16,871 What's happening here? 91 00:04:16,871 --> 00:04:18,579 Again, we're calling that print function, 92 00:04:18,579 --> 00:04:21,182 the same function that we called in hello dot py. 93 00:04:21,182 --> 00:04:23,140 But in particular what's inside the parentheses 94 00:04:23,140 --> 00:04:25,280 is slightly different notation. 95 00:04:25,280 --> 00:04:28,270 So the first thing that's slightly different is that the string-- 96 00:04:28,270 --> 00:04:30,550 the text enclosed in double quotation marks-- 97 00:04:30,550 --> 00:04:34,780 begins with the letter F. This is a new feature of Python version 3.6-- 98 00:04:34,780 --> 00:04:39,670 the latest version-- called the format strings, which let us take a string, 99 00:04:39,670 --> 00:04:45,100 take text and substitute information by filling in blanks in the string 100 00:04:45,100 --> 00:04:48,880 wherever we want to put a placeholder for some other value, for instance. 101 00:04:48,880 --> 00:04:50,740 And so what that's going to allow us to do 102 00:04:50,740 --> 00:04:53,440 is say something like print hello comma. 103 00:04:53,440 --> 00:04:55,600 And then these curly braces surrounding the word 104 00:04:55,600 --> 00:04:59,680 name mean take the variable name and plug it 105 00:04:59,680 --> 00:05:02,162 into this format string inserted here. 106 00:05:02,162 --> 00:05:03,870 So whatever name gets typed in, that gets 107 00:05:03,870 --> 00:05:06,220 saved into this variable called name. 108 00:05:06,220 --> 00:05:10,150 And then when I print something out, I'm printing out the word hello comma, 109 00:05:10,150 --> 00:05:13,240 and then here, we're going to insert whatever that name was 110 00:05:13,240 --> 00:05:16,200 that was passed in via the input. 111 00:05:16,200 --> 00:05:22,130 So if I try to run this program now by running Python name dot py-- 112 00:05:22,130 --> 00:05:24,140 because that's the name of this Python file-- 113 00:05:24,140 --> 00:05:26,940 and I press Return, nothing appears to happen. 114 00:05:26,940 --> 00:05:29,420 And the reason for that is that on line one 115 00:05:29,420 --> 00:05:32,210 it's waiting for me to provide some sort of input. 116 00:05:32,210 --> 00:05:35,640 Recall that line one, I have name equals input this function. 117 00:05:35,640 --> 00:05:38,990 And so if I type in my name, for example, Brian, then on the next line 118 00:05:38,990 --> 00:05:40,670 it says hello Brian. 119 00:05:40,670 --> 00:05:43,010 So name was my name. 120 00:05:43,010 --> 00:05:46,880 And then inside of the format string, inside the print statement on line two, 121 00:05:46,880 --> 00:05:50,577 it substituted my name in where these double curly braces were. 122 00:05:50,577 --> 00:05:53,660 And if I were to run this again, typing in someone else's name like David, 123 00:05:53,660 --> 00:05:56,750 then the next line says hello David, plugging in that new name 124 00:05:56,750 --> 00:05:59,100 into that format string as well. 125 00:05:59,100 --> 00:06:01,070 So that was an example of variables in Python 126 00:06:01,070 --> 00:06:05,090 as well as format strings, which are a special type of string in Python. 127 00:06:05,090 --> 00:06:08,480 Questions about that we've seen so far? 128 00:06:08,480 --> 00:06:08,980 Yeah? 129 00:06:08,980 --> 00:06:12,900 AUDIENCE: [INAUDIBLE]? 130 00:06:12,900 --> 00:06:14,420 BRIAN YU: Yes. 131 00:06:14,420 --> 00:06:18,470 So the question was can we also pass in a name via command line argument? 132 00:06:18,470 --> 00:06:22,390 And yes, Python does have ways of interpreting command line arguments. 133 00:06:22,390 --> 00:06:25,032 You'll have to use a separate package in Python that 134 00:06:25,032 --> 00:06:26,240 allows you to deal with that. 135 00:06:26,240 --> 00:06:28,370 It's called the sys package, s-y-s. 136 00:06:28,370 --> 00:06:31,620 And using that package, you can interpret command line arguments 137 00:06:31,620 --> 00:06:33,620 and do things with those command line arguments. 138 00:06:33,620 --> 00:06:35,390 We won't explore those too heavily in this course, 139 00:06:35,390 --> 00:06:38,420 because our focus is going to be to quickly move away from the command line 140 00:06:38,420 --> 00:06:40,961 and start moving towards building web applications in Python. 141 00:06:40,961 --> 00:06:45,950 But yes, you can in Python use command line arguments to get information 142 00:06:45,950 --> 00:06:48,710 from the user as well. 143 00:06:48,710 --> 00:06:52,820 Other questions before we keep going on? 144 00:06:52,820 --> 00:06:55,009 So this name on line one was the first example 145 00:06:55,009 --> 00:06:57,050 of what we're going to call a variable in Python. 146 00:06:57,050 --> 00:07:01,967 Just a place in our Python code where we can store data of different types. 147 00:07:01,967 --> 00:07:04,550 And so let's take a look at the different types of information 148 00:07:04,550 --> 00:07:06,980 that we can store inside of a Python variable, 149 00:07:06,980 --> 00:07:09,330 and just look at a couple of examples of that. 150 00:07:09,330 --> 00:07:13,910 So right here what we have is a Python program called variables dot py. 151 00:07:13,910 --> 00:07:17,450 And what this does is it defines four different Python variables. 152 00:07:17,450 --> 00:07:20,270 And these variables all have different types. 153 00:07:20,270 --> 00:07:24,770 And so on line one, I've defined the variable i to be equal to 28. 154 00:07:24,770 --> 00:07:28,010 And now i is going to be a variable that stores the number 28. 155 00:07:28,010 --> 00:07:31,070 But in particular, it's storing a particular type of information. 156 00:07:31,070 --> 00:07:34,730 The number 28 is an integer, where integers are 0, 1, 2, 3, 4, 157 00:07:34,730 --> 00:07:37,400 and the negative 1, negative 2, negative 3, et cetera. 158 00:07:37,400 --> 00:07:40,130 And so i in this case is just an integer value. 159 00:07:40,130 --> 00:07:43,130 And so we see here that Python can store integers as variables. 160 00:07:43,130 --> 00:07:47,880 And then we're going to print out that i is 28, for instance in this case. 161 00:07:47,880 --> 00:07:51,470 And then on line four, I'm defining a new variable 162 00:07:51,470 --> 00:07:54,227 called f, which is equal to 2.8. 163 00:07:54,227 --> 00:07:56,810 And so this shows you that Python can store not only integers, 164 00:07:56,810 --> 00:08:00,140 but floating point values as well, values that have a decimal in it. 165 00:08:00,140 --> 00:08:03,060 And so this is a different type of variable altogether. 166 00:08:03,060 --> 00:08:06,200 And so that will print out f is 2.8, for example. 167 00:08:06,200 --> 00:08:09,860 But it's not just numbers that Python can store as variables. 168 00:08:09,860 --> 00:08:13,596 We saw in name dot py-- the example from just a moment ago-- 169 00:08:13,596 --> 00:08:15,720 that we can use variables to store strings as well, 170 00:08:15,720 --> 00:08:19,430 text that can be used in order to store a name, for example, 171 00:08:19,430 --> 00:08:20,610 inside of a variable. 172 00:08:20,610 --> 00:08:22,340 And we can store other types as well. 173 00:08:22,340 --> 00:08:26,150 Down here line seven, we see that b is set to true. 174 00:08:26,150 --> 00:08:28,430 So Python has a special type called bool, 175 00:08:28,430 --> 00:08:31,280 which stands for Boolean values, where a Boolean value is just 176 00:08:31,280 --> 00:08:33,039 a value that is either true or false. 177 00:08:33,039 --> 00:08:36,590 It represents where the something is positive or negative, for instance. 178 00:08:36,590 --> 00:08:40,700 And Python has a special keyword called True with a capital T that 179 00:08:40,700 --> 00:08:43,370 represents the Boolean value true. 180 00:08:43,370 --> 00:08:47,990 And likewise there's also a false value that represents a false Boolean 181 00:08:47,990 --> 00:08:49,740 value as well. 182 00:08:49,740 --> 00:08:51,920 And finally, Python also has a particular type 183 00:08:51,920 --> 00:08:56,150 called the None type, which only has one possible value, just called a None. 184 00:08:56,150 --> 00:09:00,110 And a none type is just a way in Python to represent the idea 185 00:09:00,110 --> 00:09:02,070 that a variable has no value. 186 00:09:02,070 --> 00:09:04,960 So if we want a variable that doesn't have value for some reason, 187 00:09:04,960 --> 00:09:06,793 and we might see examples later of when that 188 00:09:06,793 --> 00:09:08,960 could be useful or helpful or practical, you'll 189 00:09:08,960 --> 00:09:11,990 often see capital N None used to represent 190 00:09:11,990 --> 00:09:15,930 a kind of variable that just isn't storing any information whatsoever. 191 00:09:15,930 --> 00:09:21,950 So if I were to run variables dot py, what I get is that i is 28, f is 2.8, 192 00:09:21,950 --> 00:09:23,720 b is false, N is None. 193 00:09:23,720 --> 00:09:28,007 Note that I never told my program that i is going to be an integer, 194 00:09:28,007 --> 00:09:29,840 or f is going to be a floating point number, 195 00:09:29,840 --> 00:09:31,850 or b is going to be a Boolean value. 196 00:09:31,850 --> 00:09:33,980 Python figures this out for itself. 197 00:09:33,980 --> 00:09:37,730 When I say i equals 28, Python knows that if I'm assigning the number 28 198 00:09:37,730 --> 00:09:40,727 to i, then i must be in integer value. 199 00:09:40,727 --> 00:09:43,310 And so if you're familiar with other languages like C or Java, 200 00:09:43,310 --> 00:09:45,440 where you're used to having to explicitly write out 201 00:09:45,440 --> 00:09:47,860 the name of the type for any particular variable, 202 00:09:47,860 --> 00:09:49,970 know that Python doesn't require you to do that, 203 00:09:49,970 --> 00:09:54,020 and just lets you take a variable and assign it to any given value 204 00:09:54,020 --> 00:09:57,830 without needing to specify explicitly what the type of that value 205 00:09:57,830 --> 00:09:59,404 actually is. 206 00:09:59,404 --> 00:10:00,570 Questions about that so far? 207 00:10:00,570 --> 00:10:03,704 208 00:10:03,704 --> 00:10:05,870 So let's take a look at some of the other constructs 209 00:10:05,870 --> 00:10:10,100 that we can begin to build up by using Python and its various language 210 00:10:10,100 --> 00:10:11,010 features. 211 00:10:11,010 --> 00:10:13,820 Let's take a look at conditions dot py. 212 00:10:13,820 --> 00:10:16,910 And so what we're going to do here is say 213 00:10:16,910 --> 00:10:21,240 that we have a variable called x that's set equal to some number, for example. 214 00:10:21,240 --> 00:10:25,110 Maybe the number 28, just to take an example. 215 00:10:25,110 --> 00:10:28,580 And what we have here on line three are conditional statements, 216 00:10:28,580 --> 00:10:31,250 if statements, which are effectively branches in the code 217 00:10:31,250 --> 00:10:34,770 where depending upon whether or not something is true or false, 218 00:10:34,770 --> 00:10:37,014 we can decide which code you want to execute. 219 00:10:37,014 --> 00:10:38,930 So let's take a look at what's happening here. 220 00:10:38,930 --> 00:10:42,830 We say on line three if x is greater than 0, 221 00:10:42,830 --> 00:10:47,570 then anything indented underneath this if statement, as we would call it, 222 00:10:47,570 --> 00:10:51,050 is code that will only run if x is greater than 0. 223 00:10:51,050 --> 00:10:53,840 So if x is greater than 0, then here's what's going to happen. 224 00:10:53,840 --> 00:10:56,780 All of these indented lines, in which case now there's only one, 225 00:10:56,780 --> 00:11:00,140 we're going to print out the string x is positive. 226 00:11:00,140 --> 00:11:03,600 Meanwhile, el if is short for else if. 227 00:11:03,600 --> 00:11:07,970 In other words, else otherwise if x wasn't greater than 0, 228 00:11:07,970 --> 00:11:11,900 if x is less than 0, then let's run this indented line here, 229 00:11:11,900 --> 00:11:14,460 print x is negative. 230 00:11:14,460 --> 00:11:18,000 Else otherwise, if it was neither greater than 0, nor less than 0, 231 00:11:18,000 --> 00:11:19,680 there's only one remaining possibility. 232 00:11:19,680 --> 00:11:22,320 We can print out the fact that x is 0. 233 00:11:22,320 --> 00:11:24,990 And this indentation in Python is something you'll see a lot. 234 00:11:24,990 --> 00:11:27,170 The indentation in Python is actually required. 235 00:11:27,170 --> 00:11:28,920 Unlike several other programming languages 236 00:11:28,920 --> 00:11:31,230 where indentation is a style thing, where 237 00:11:31,230 --> 00:11:35,130 it's nice and helpful from a readability perspective to include indentation, 238 00:11:35,130 --> 00:11:39,130 but it's not strictly necessary, in Python this indentation is necessary. 239 00:11:39,130 --> 00:11:41,670 This is how you tell the Python interpreter 240 00:11:41,670 --> 00:11:44,580 this is the code that is contained inside of this if statement. 241 00:11:44,580 --> 00:11:48,430 This is the code that should run if this if statement is true. 242 00:11:48,430 --> 00:11:51,810 So if I had multiple lines that I wanted to run, if x were greater than 0 243 00:11:51,810 --> 00:11:56,490 for instance, I would have multiple lines all indented inside of that if 244 00:11:56,490 --> 00:11:58,120 statement as well. 245 00:11:58,120 --> 00:12:02,477 So if I were to go over here and run this program now, rather than print out 246 00:12:02,477 --> 00:12:04,560 three things, because I have three different print 247 00:12:04,560 --> 00:12:09,330 statements, if I run in conditions dot py, I just see x is positive. 248 00:12:09,330 --> 00:12:14,010 Because it caught on that first if condition, if x is greater than 0. 249 00:12:14,010 --> 00:12:15,960 And it printed out that x is positive. 250 00:12:15,960 --> 00:12:21,720 If x were negative 28 instead, and I ran that same program, now x is negative. 251 00:12:21,720 --> 00:12:25,110 And likewise, if I had replaced x with just 0 for instance, 252 00:12:25,110 --> 00:12:29,130 and run that again, now I just see that x is 0, for instance. 253 00:12:29,130 --> 00:12:32,070 And so depending upon the value of x, I can conditionally 254 00:12:32,070 --> 00:12:34,834 determine which way to go in the code. 255 00:12:34,834 --> 00:12:36,000 Questions about that so far? 256 00:12:36,000 --> 00:12:38,700 257 00:12:38,700 --> 00:12:40,290 Let's keep going then. 258 00:12:40,290 --> 00:12:43,470 So thus far we've seen examples of variables in Python 259 00:12:43,470 --> 00:12:45,630 that are able to store single values, effectively, 260 00:12:45,630 --> 00:12:48,360 a single number, whether it's integer or floating point 261 00:12:48,360 --> 00:12:51,480 number or a single Boolean value, like true or false. 262 00:12:51,480 --> 00:12:53,820 But Python is very good at also supporting 263 00:12:53,820 --> 00:12:57,570 storing sequences of data where we have multiple values that 264 00:12:57,570 --> 00:12:59,386 are combined together under one name. 265 00:12:59,386 --> 00:13:01,510 And there are a bunch of different ways to do that. 266 00:13:01,510 --> 00:13:04,340 So I'll show you sequences dot py now. 267 00:13:04,340 --> 00:13:06,390 And so in sequences dot py, I've given you 268 00:13:06,390 --> 00:13:08,850 three examples of variables of different types 269 00:13:08,850 --> 00:13:11,980 that are all sequences of data in some form. 270 00:13:11,980 --> 00:13:14,130 So on line one, I have a variable called name, 271 00:13:14,130 --> 00:13:16,410 which is just storing the string Alice. 272 00:13:16,410 --> 00:13:18,150 This is something we've seen before where 273 00:13:18,150 --> 00:13:19,950 we have a string, which is just text that's 274 00:13:19,950 --> 00:13:21,690 being stored inside of a variable. 275 00:13:21,690 --> 00:13:24,840 But one helpful way to think about a string like the word Alice 276 00:13:24,840 --> 00:13:26,940 is that it's really just a sequence of characters. 277 00:13:26,940 --> 00:13:29,790 It's the character capital A, followed by the character lowercase, 278 00:13:29,790 --> 00:13:32,760 l followed by lowercase i, c, e. et cetera. 279 00:13:32,760 --> 00:13:35,730 And this way of thinking about a variable 280 00:13:35,730 --> 00:13:38,826 makes it easy to say what if I wanted to just get 281 00:13:38,826 --> 00:13:41,700 the second character of the name, or the third character of the name, 282 00:13:41,700 --> 00:13:42,610 for instance? 283 00:13:42,610 --> 00:13:45,330 You can treat that long string as just a sequence 284 00:13:45,330 --> 00:13:48,690 of the individual constituent parts that make it up. 285 00:13:48,690 --> 00:13:51,510 On line two you're looking at an example of what's 286 00:13:51,510 --> 00:13:54,720 called a Python tuple, which is a way of grouping a couple of values 287 00:13:54,720 --> 00:13:56,860 together in a single name. 288 00:13:56,860 --> 00:14:00,690 So if I wanted to store in Python an xy coordinate, for example, 289 00:14:00,690 --> 00:14:04,410 like, on a graph if I wanted to store a particular point on that graph, 290 00:14:04,410 --> 00:14:08,040 I might store it as follows, where I say the coordinates are, 291 00:14:08,040 --> 00:14:11,730 and then in parentheses 10.0, 20.0. 292 00:14:11,730 --> 00:14:15,300 And so now both of those values are stored as a single name, 293 00:14:15,300 --> 00:14:17,220 coordinates, as opposed to needing to store 294 00:14:17,220 --> 00:14:21,120 two variables like a coordinates x variable and a coordinates y variable, 295 00:14:21,120 --> 00:14:25,330 I can group them together and just store them under a single name as well. 296 00:14:25,330 --> 00:14:27,840 And then finally on line three, we see an example 297 00:14:27,840 --> 00:14:29,590 of what's called a Python list. 298 00:14:29,590 --> 00:14:32,580 And this is a very powerful data type in Python. 299 00:14:32,580 --> 00:14:36,530 And a list is a data type that lets us store a bunch of different values 300 00:14:36,530 --> 00:14:37,920 all together in one. 301 00:14:37,920 --> 00:14:41,220 And so here I have a list of individual people's names. 302 00:14:41,220 --> 00:14:44,594 And so a list in Python is denoted by the square brackets. 303 00:14:44,594 --> 00:14:47,010 So I open the square bracket and then have the first thing 304 00:14:47,010 --> 00:14:48,750 in the list, which is the name Alice. 305 00:14:48,750 --> 00:14:51,930 And each of the elements in the list are separated by commas. 306 00:14:51,930 --> 00:14:54,180 So Alice is the first thing in this list, 307 00:14:54,180 --> 00:14:57,700 Bob is the second thing in the list, Charlie is the third thing in the list. 308 00:14:57,700 --> 00:15:01,260 And so this is an example of a list in Python 309 00:15:01,260 --> 00:15:05,100 that is all stored under the variable name names. 310 00:15:05,100 --> 00:15:08,790 So using those lists we can begin to perform operations on them. 311 00:15:08,790 --> 00:15:13,830 And one nice feature of Python is that I don't just have to write a Python file 312 00:15:13,830 --> 00:15:15,180 and then run that Python file. 313 00:15:15,180 --> 00:15:17,250 And that's the only way to run Python code. 314 00:15:17,250 --> 00:15:21,600 Python has a sort of a live interpreter that lets me type code 315 00:15:21,600 --> 00:15:23,890 and see the result of it happening in real time. 316 00:15:23,890 --> 00:15:26,790 So if I just type Python instead of Python space, 317 00:15:26,790 --> 00:15:29,310 the name of a Python file I want to run, what happens 318 00:15:29,310 --> 00:15:31,740 is that I've opened up the Python interpreter, which 319 00:15:31,740 --> 00:15:35,010 is a place where I can line at a time type of line of Python code 320 00:15:35,010 --> 00:15:36,377 and immediately see the result. 321 00:15:36,377 --> 00:15:38,710 And for our purposes this is going to be pretty helpful. 322 00:15:38,710 --> 00:15:42,510 So you can do the exact same things you could do in a Python file. 323 00:15:42,510 --> 00:15:47,790 I can say x equals 28, for example and press Return. 324 00:15:47,790 --> 00:15:49,770 And now that line of Python is executed. 325 00:15:49,770 --> 00:15:51,960 And now if I were to just type x, for example, 326 00:15:51,960 --> 00:15:54,240 it will show me that the value of x is 28. 327 00:15:54,240 --> 00:15:57,970 And I can add any other Python code that I want here. 328 00:15:57,970 --> 00:16:03,300 So if x is greater than 0, then print x is positive. 329 00:16:03,300 --> 00:16:07,050 And now that prints out the fact that x is positive. 330 00:16:07,050 --> 00:16:09,747 And so I'm able to run Python code just like this. 331 00:16:09,747 --> 00:16:11,580 And the reason I'm doing this is that we can 332 00:16:11,580 --> 00:16:16,860 begin to see some of the features of Python data types like sequences 333 00:16:16,860 --> 00:16:18,630 by using the Python interpreter. 334 00:16:18,630 --> 00:16:22,530 So if I had a name equals Alice, like I had before, 335 00:16:22,530 --> 00:16:26,650 the way that you access individual elements of a Python sequence 336 00:16:26,650 --> 00:16:29,400 whether it's a string representing a bunch of different characters 337 00:16:29,400 --> 00:16:31,830 or a tuple representing a couple of different values 338 00:16:31,830 --> 00:16:35,310 or a list of even more values, is that I can do name it, 339 00:16:35,310 --> 00:16:38,190 and then in square brackets, the index that I 340 00:16:38,190 --> 00:16:42,300 want to access, where the first thing in the sequence is index 0. 341 00:16:42,300 --> 00:16:45,390 So if I did name, square bracket 0, what is that going to be? 342 00:16:45,390 --> 00:16:48,300 343 00:16:48,300 --> 00:16:51,690 Capital A. That's the first thing in the string Alice. 344 00:16:51,690 --> 00:16:53,800 The very first character is just that capital A. 345 00:16:53,800 --> 00:16:56,579 And likewise, name, square bracket 1, that's 346 00:16:56,579 --> 00:16:58,620 going to be the second character of Alice's name, 347 00:16:58,620 --> 00:17:00,600 where l is the second character. 348 00:17:00,600 --> 00:17:05,280 So it's sort of what we call a zero index system, whereby 349 00:17:05,280 --> 00:17:08,520 the first thing in the string Alice is number 0 and the second thing 350 00:17:08,520 --> 00:17:09,569 is number 1. 351 00:17:09,569 --> 00:17:12,209 And so that's a typical computer science convention. 352 00:17:12,209 --> 00:17:14,250 It's true in other programming languages as well. 353 00:17:14,250 --> 00:17:17,609 But know that square bracket 0 gets you at the first thing in the sequence. 354 00:17:17,609 --> 00:17:20,440 Square bracket 1 is the second thing, so on and so forth. 355 00:17:20,440 --> 00:17:25,980 And so if I had coordinates equals 10.0, 20.0 for instance, 356 00:17:25,980 --> 00:17:28,560 I could use the coordinates square brackets 357 00:17:28,560 --> 00:17:31,920 0 to get it just the first coordinate, and likewise, I 358 00:17:31,920 --> 00:17:36,720 could do coordinate square bracket 1 to get it just the second coordinate. 359 00:17:36,720 --> 00:17:43,710 And similarly, if I had a list of names that was Alice and Bob and Charlie, 360 00:17:43,710 --> 00:17:47,970 then I could do names, square brackets 0 to get at the first name, 361 00:17:47,970 --> 00:17:51,600 name square bracket 1 to get the second name, and name square bracket 2 362 00:17:51,600 --> 00:17:52,710 get at the third name. 363 00:17:52,710 --> 00:17:56,201 And what would happen if I tried name square bracket 3? 364 00:17:56,201 --> 00:17:58,436 AUDIENCE: [INAUDIBLE]. 365 00:17:58,436 --> 00:18:01,500 BRIAN YU: So what I get is a Python exception, effectively 366 00:18:01,500 --> 00:18:04,390 an error of some sort that tells me that something went wrong. 367 00:18:04,390 --> 00:18:08,010 And in this case, the type of the exception is index error. 368 00:18:08,010 --> 00:18:10,560 And it says index lists index out of range. 369 00:18:10,560 --> 00:18:13,470 And so the interpretation of that is that this index that I provided, 370 00:18:13,470 --> 00:18:17,370 this number, name square bracket 3 is out of the range of the list. 371 00:18:17,370 --> 00:18:21,927 There is no item in the names list that has index number 3, 372 00:18:21,927 --> 00:18:23,760 and therefore Python can't access it for me. 373 00:18:23,760 --> 00:18:26,670 And so if I'm trying to ask Python or do something that it can't do, 374 00:18:26,670 --> 00:18:28,710 oftentimes I'll get an exception of this form. 375 00:18:28,710 --> 00:18:31,740 And learning to become familiar with these exceptions 376 00:18:31,740 --> 00:18:34,260 as you begin to see them as you work with Python programming 377 00:18:34,260 --> 00:18:38,040 will help you to figure out where the cause of the source of the area 378 00:18:38,040 --> 00:18:41,040 is, which can then help you to then go back and debug 379 00:18:41,040 --> 00:18:43,660 and figure out what went wrong. 380 00:18:43,660 --> 00:18:48,359 So those were variables and different types of data and conditions in Python. 381 00:18:48,359 --> 00:18:50,400 Let's take a look at some of the other constructs 382 00:18:50,400 --> 00:18:53,191 that we can have in the Python programming language, in particular, 383 00:18:53,191 --> 00:18:58,030 let's take a look at loops and how we might repeat code multiple times. 384 00:18:58,030 --> 00:19:02,100 And so here in loops 0 dot py i have just two lines. 385 00:19:02,100 --> 00:19:06,340 So on line one I say for i in range 5. 386 00:19:06,340 --> 00:19:09,450 And then on line two, I'm printing out i. 387 00:19:09,450 --> 00:19:12,450 And so what this program is effectively doing is on line one 388 00:19:12,450 --> 00:19:17,320 I'm saying let's take this variable i and run it through this loop. 389 00:19:17,320 --> 00:19:21,120 This what we call a for loop through a range of five numbers, 390 00:19:21,120 --> 00:19:25,770 ranging from 0 all the way up to but not including the number 5, 391 00:19:25,770 --> 00:19:30,510 such that if I run the loops 0 dot py what I get 392 00:19:30,510 --> 00:19:35,760 is that I get five numbers printed out, 0, and then 1, and then 2, and then 3, 393 00:19:35,760 --> 00:19:36,930 and then 4. 394 00:19:36,930 --> 00:19:40,500 Because this loop, this loop happened five times. 395 00:19:40,500 --> 00:19:42,660 And each time the value of i changed. 396 00:19:42,660 --> 00:19:44,050 The first time it was 0. 397 00:19:44,050 --> 00:19:47,170 That it incremented to 1, and then 2, and then 3, and then 4. 398 00:19:47,170 --> 00:19:49,260 And then it doesn't include the final number 5. 399 00:19:49,260 --> 00:19:51,120 It goes up to, but not including the 5. 400 00:19:51,120 --> 00:19:54,287 And as a result I get numbers printed out five times. 401 00:19:54,287 --> 00:19:56,370 If I wanted to print out 10 numbers, for instance, 402 00:19:56,370 --> 00:19:58,410 I could change range to range 10. 403 00:19:58,410 --> 00:20:02,280 And now running loop 0 dot py prints out 0 all the way up through 9, 404 00:20:02,280 --> 00:20:03,850 for example. 405 00:20:03,850 --> 00:20:06,570 So that's an example of a simple loop in Python. 406 00:20:06,570 --> 00:20:09,030 But Python supports other types of loops as well, 407 00:20:09,030 --> 00:20:12,180 in particular, for looping over a sequence. 408 00:20:12,180 --> 00:20:15,720 So we saw in the last example that we have a bunch of different data types 409 00:20:15,720 --> 00:20:17,670 for representing sequences of data. 410 00:20:17,670 --> 00:20:20,370 We have strings that are just individual characters. 411 00:20:20,370 --> 00:20:23,100 We have lists that are a bunch of different values 412 00:20:23,100 --> 00:20:24,340 that are grouped together. 413 00:20:24,340 --> 00:20:27,960 And so if I look at loops 1 dot py now, you'll 414 00:20:27,960 --> 00:20:31,110 see what we have here is on line one I had a final list, the same list 415 00:20:31,110 --> 00:20:31,920 as before. 416 00:20:31,920 --> 00:20:36,240 Names is equal to Alice, Bob, and Charlie, a list of three strings. 417 00:20:36,240 --> 00:20:39,060 And then on line two, I have a different style of for loop. 418 00:20:39,060 --> 00:20:43,590 I'm saying for name in names, where the intuition here 419 00:20:43,590 --> 00:20:48,480 is that I'm going to be looping over this names variable one at a time. 420 00:20:48,480 --> 00:20:51,881 And each time I'm going to call each item in that list name. 421 00:20:51,881 --> 00:20:54,630 And that's just going to be the name that I give to that variable. 422 00:20:54,630 --> 00:20:57,497 And then I'm going to print out that name inside of the for loop. 423 00:20:57,497 --> 00:21:00,330 And notice that everything inside the for loop, just like everything 424 00:21:00,330 --> 00:21:04,020 inside of my if condition needs to be indented so that Python knows 425 00:21:04,020 --> 00:21:05,730 what code is contained inside my for loop 426 00:21:05,730 --> 00:21:08,900 and what code is outside of the for loop. 427 00:21:08,900 --> 00:21:13,200 And so if I now run Python loops 1 dot py, what I get 428 00:21:13,200 --> 00:21:18,201 is Alice and then Bob and then Charlie, one name at a time, one line at a time. 429 00:21:18,201 --> 00:21:18,700 Question? 430 00:21:18,700 --> 00:21:21,969 AUDIENCE: Do sequences need to be all the same data type? 431 00:21:21,969 --> 00:21:23,050 BRIAN YU: Great question. 432 00:21:23,050 --> 00:21:26,610 So the question is, do sequences need to be all of the same data type? 433 00:21:26,610 --> 00:21:28,080 The short answer is no. 434 00:21:28,080 --> 00:21:34,170 So in a list for example, I could have a list, I'll just call it l for a list. 435 00:21:34,170 --> 00:21:37,050 That could be the number 28, and then the name Alice, 436 00:21:37,050 --> 00:21:39,180 and then the Boolean value true. 437 00:21:39,180 --> 00:21:40,770 That is technically a valid list. 438 00:21:40,770 --> 00:21:44,280 And I can say l square bracket 0 to get it the first thing in the list. 439 00:21:44,280 --> 00:21:47,370 And 1 to get it the second, and 2 to get to the third, for instance. 440 00:21:47,370 --> 00:21:49,800 But generally speaking, especially with lists, 441 00:21:49,800 --> 00:21:53,250 it's a good idea if different things in the list are of the same type. 442 00:21:53,250 --> 00:21:56,894 It's often good design to have elements of the list to be of the same type, 443 00:21:56,894 --> 00:22:00,060 because generally our lists are going to have some sort of semantic meaning. 444 00:22:00,060 --> 00:22:03,300 It's going to be a list of names, where all of the elements in the list 445 00:22:03,300 --> 00:22:04,290 should be strings. 446 00:22:04,290 --> 00:22:07,680 Or a list of numbers, where all of the elements in the list 447 00:22:07,680 --> 00:22:08,980 should be integers. 448 00:22:08,980 --> 00:22:12,580 And it's helpful to be able to treat each item in the list the same way. 449 00:22:12,580 --> 00:22:15,820 And we can only do that if items in the list are of the same type. 450 00:22:15,820 --> 00:22:17,850 So while not strictly necessary to have all 451 00:22:17,850 --> 00:22:22,590 the items in a list be of the same type, it's often a good design idea to do so. 452 00:22:22,590 --> 00:22:24,670 Good question. 453 00:22:24,670 --> 00:22:27,784 Other questions before we move on? 454 00:22:27,784 --> 00:22:34,518 AUDIENCE: Could you skip the print [INAUDIBLE] In the interpreted version, 455 00:22:34,518 --> 00:22:38,724 you don't have [INAUDIBLE]. 456 00:22:38,724 --> 00:22:40,640 BRIAN YU: So the question is-- great question. 457 00:22:40,640 --> 00:22:42,900 The question is in the interpreted version 458 00:22:42,900 --> 00:22:45,550 when I'm trying to display a value, I didn't need the print. 459 00:22:45,550 --> 00:22:48,730 I just typed l0 instead of print l0 in order 460 00:22:48,730 --> 00:22:50,510 to get the first thing in the list. 461 00:22:50,510 --> 00:22:52,960 This is something unique to the Python interpreter 462 00:22:52,960 --> 00:22:55,570 that the interpreter if I just type in a value, 463 00:22:55,570 --> 00:22:58,790 Python will tell me what's currently stored in that value. 464 00:22:58,790 --> 00:23:00,850 But if I'm running a Python program, then I 465 00:23:00,850 --> 00:23:03,550 do explicitly need that print function in order 466 00:23:03,550 --> 00:23:07,150 to say this is a value that I want to print out to the screen. 467 00:23:07,150 --> 00:23:10,420 So it's a slight difference between the way the interpreter works live, 468 00:23:10,420 --> 00:23:13,000 versus when I'm running it just through a Python file. 469 00:23:13,000 --> 00:23:16,204 I could equivalently type print l0 in the interpreter. 470 00:23:16,204 --> 00:23:17,870 And that would produce the same results. 471 00:23:17,870 --> 00:23:21,670 But if I'm running it in a Python file, like, a file that ends with dot py, 472 00:23:21,670 --> 00:23:25,300 then I need to have the print line there. 473 00:23:25,300 --> 00:23:27,570 Good question. 474 00:23:27,570 --> 00:23:31,510 We'll take a quick look at some of the other more advanced data types 475 00:23:31,510 --> 00:23:33,576 that exist in Python, and then we'll move on 476 00:23:33,576 --> 00:23:35,450 to taking a look at a couple of other things. 477 00:23:35,450 --> 00:23:37,450 So in addition to supporting lists, which 478 00:23:37,450 --> 00:23:40,270 are an ordered sequence of data where we have 479 00:23:40,270 --> 00:23:42,580 a first item and a second item and a third item, 480 00:23:42,580 --> 00:23:46,250 Python also has support for other collections of data as well. 481 00:23:46,250 --> 00:23:48,490 And so one of those examples is a set where 482 00:23:48,490 --> 00:23:55,050 a set is just a collection of items where no item shows up twice. 483 00:23:55,050 --> 00:23:57,860 And in particular, a set doesn't have any particular order to it. 484 00:23:57,860 --> 00:24:01,210 So the only thing we care about is a particular value in the set, 485 00:24:01,210 --> 00:24:03,830 or is a particular value not in the set? 486 00:24:03,830 --> 00:24:07,150 And so line one here, I've said s is equal to set, 487 00:24:07,150 --> 00:24:10,420 where set is just a function that creates an empty set for me. 488 00:24:10,420 --> 00:24:12,570 On line two, I've added the number 1 to the set. 489 00:24:12,570 --> 00:24:15,220 On line three, I've added the number 3 to the set. 490 00:24:15,220 --> 00:24:17,380 On line four, I've added the number 5 to the set. 491 00:24:17,380 --> 00:24:20,680 And on line five, just for the fun of it, I've added the number 3 to the set 492 00:24:20,680 --> 00:24:21,520 again. 493 00:24:21,520 --> 00:24:25,370 But the rules for a set is that items in the set are unique. 494 00:24:25,370 --> 00:24:28,810 So if I try to add a number or a value that's already in the set to the set 495 00:24:28,810 --> 00:24:32,400 again, then the result of that is going to be no change to the set. 496 00:24:32,400 --> 00:24:34,870 And so if I print the set out on the last line, 497 00:24:34,870 --> 00:24:38,350 and I run sets dot py, what I get is just a set 498 00:24:38,350 --> 00:24:41,920 1, 3, and 5, because those are the only three numbers that 499 00:24:41,920 --> 00:24:43,810 are actually inside of that set. 500 00:24:43,810 --> 00:24:47,120 And so if ever you don't really care about the order of the information, 501 00:24:47,120 --> 00:24:49,150 because sets doesn't preserve which thing 502 00:24:49,150 --> 00:24:50,790 came first, second, third, fourth-- 503 00:24:50,790 --> 00:24:54,430 and I just care about which things are inside of the set or not in the set-- 504 00:24:54,430 --> 00:24:59,780 then I can use this notation in order to describe that as well. 505 00:24:59,780 --> 00:25:03,860 And one final data type we'll take a look at are Python dictionaries. 506 00:25:03,860 --> 00:25:06,550 So dictionaries are yet another data structure in Python 507 00:25:06,550 --> 00:25:11,440 which are used in order to map certain values on to other values. 508 00:25:11,440 --> 00:25:13,750 And they're often used when we want to try and indicate 509 00:25:13,750 --> 00:25:17,280 some sort of relationship between a former value and a latter value. 510 00:25:17,280 --> 00:25:19,450 And so what we see in dictionaries dot py here 511 00:25:19,450 --> 00:25:22,000 is an example where I in my Python program 512 00:25:22,000 --> 00:25:25,050 might want to store the ages of different people 513 00:25:25,050 --> 00:25:26,350 that I'm keeping track of. 514 00:25:26,350 --> 00:25:30,970 And so what I have here line one is I've created a Python dictionary 515 00:25:30,970 --> 00:25:34,180 that maps what are called keys to values. 516 00:25:34,180 --> 00:25:36,620 And in the case of my ages dictionary, the key 517 00:25:36,620 --> 00:25:39,830 are all going to be the names of people. 518 00:25:39,830 --> 00:25:43,960 So in this case, I have the key Alice, which is mapped to the value 22. 519 00:25:43,960 --> 00:25:46,900 And the semantic interpretation of this is that Alice is 22 years old 520 00:25:46,900 --> 00:25:49,180 and Bob is 27 years old. 521 00:25:49,180 --> 00:25:51,880 And so what you'll notice is that the syntax for that 522 00:25:51,880 --> 00:25:55,070 is that a dictionary is defined by curly braces on either end. 523 00:25:55,070 --> 00:25:59,320 And then the key, which is some value, followed by a colon, 524 00:25:59,320 --> 00:26:01,360 followed by what its value is. 525 00:26:01,360 --> 00:26:06,400 So Alice colon 22 means I'm going to put Alice in my ages dictionary, 526 00:26:06,400 --> 00:26:08,650 and then set its value to be 22. 527 00:26:08,650 --> 00:26:10,840 And likewise, I'm putting Bob into the dictionary 528 00:26:10,840 --> 00:26:13,010 and setting its value to be 27. 529 00:26:13,010 --> 00:26:15,640 And if I wanted to add something to the dictionary later, 530 00:26:15,640 --> 00:26:17,460 I could do it like this on line two. 531 00:26:17,460 --> 00:26:20,020 I'm adding Charlie to my ages dictionary. 532 00:26:20,020 --> 00:26:21,400 And Charlie is 30. 533 00:26:21,400 --> 00:26:23,430 That is the value that it is mapped to. 534 00:26:23,430 --> 00:26:27,085 And if I wanted to edit the value of one of the variables later on, 535 00:26:27,085 --> 00:26:31,630 a line like this, ages Alice plus equals 1 536 00:26:31,630 --> 00:26:37,030 is a shorthand way of saying take whatever Alice maps to in my age 537 00:26:37,030 --> 00:26:39,100 dictionary and increase its value by 1. 538 00:26:39,100 --> 00:26:41,462 It was formerly 22, now it should be 23. 539 00:26:41,462 --> 00:26:43,420 If I wanted to write this out in a longer form, 540 00:26:43,420 --> 00:26:48,730 I could say ages Alice equals ages Alice plus 1 541 00:26:48,730 --> 00:26:54,660 to say update the value of ages Alice, and set it equal to whatever 542 00:26:54,660 --> 00:26:57,322 ages Alice was a plus 1. 543 00:26:57,322 --> 00:26:59,780 But often a shorthand convention for that is plus equals 1, 544 00:26:59,780 --> 00:27:01,910 meaning increase its value by 1. 545 00:27:01,910 --> 00:27:03,920 Those two lines are identical. 546 00:27:03,920 --> 00:27:07,710 And then finally at the end I'm printing out this ages dictionary. 547 00:27:07,710 --> 00:27:11,140 And so if I run the dictionaries dot py, what I get 548 00:27:11,140 --> 00:27:15,220 is this dictionary where Alice's name is mapped to the number 23, 549 00:27:15,220 --> 00:27:19,180 Bob's name is mapped to the number 27, Charlie's name is not to the number 30. 550 00:27:19,180 --> 00:27:21,370 And so that's an example of a dictionary in Python 551 00:27:21,370 --> 00:27:24,450 that lets us map keys and values together. 552 00:27:24,450 --> 00:27:27,280 And so these are all just a whole bunch of different data types 553 00:27:27,280 --> 00:27:28,240 that exist in Python. 554 00:27:28,240 --> 00:27:31,570 Python is a large language with a bunch of different features and data types 555 00:27:31,570 --> 00:27:33,440 that are built into the language. 556 00:27:33,440 --> 00:27:35,560 But these are some of the most common data types, 557 00:27:35,560 --> 00:27:37,960 ones that will likely frequently come up as you 558 00:27:37,960 --> 00:27:40,090 begin to work on programming in Python. 559 00:27:40,090 --> 00:27:42,220 Totally OK if you haven't internalized all of what 560 00:27:42,220 --> 00:27:44,740 each one of those data structures is and what's different about all of them 561 00:27:44,740 --> 00:27:45,620 just yet. 562 00:27:45,620 --> 00:27:48,190 But as we begin to design web applications in Python, 563 00:27:48,190 --> 00:27:50,590 you'll hopefully start to get a sense for when might it 564 00:27:50,590 --> 00:27:53,590 be appropriate to use a dictionary in order to represent data, 565 00:27:53,590 --> 00:27:58,310 or use a list to represent data when we're designing our web applications. 566 00:27:58,310 --> 00:28:01,030 So we've looked at data types in Python. 567 00:28:01,030 --> 00:28:04,000 Now let's take a look at functions in Python. 568 00:28:04,000 --> 00:28:09,610 So here we'll open up functions dot py and see what's going on here. 569 00:28:09,610 --> 00:28:12,881 So line one, I've defined a new function in Python. 570 00:28:12,881 --> 00:28:15,880 We've seen built in functions like the print function that prints things 571 00:28:15,880 --> 00:28:19,300 to the screen, or the input function that gets input from the user. 572 00:28:19,300 --> 00:28:23,080 I'm now defining my own function called square. 573 00:28:23,080 --> 00:28:26,180 So on line one I say def, meaning I want to define a new function. 574 00:28:26,180 --> 00:28:28,240 This function is going to be called square. 575 00:28:28,240 --> 00:28:32,370 And it's going to take one argument that I'm arbitrarily just going to call x. 576 00:28:32,370 --> 00:28:34,990 Now just like in if statements, we indented everything 577 00:28:34,990 --> 00:28:36,730 inside the if statement, and in for loops 578 00:28:36,730 --> 00:28:38,830 we indented everything inside the loop. 579 00:28:38,830 --> 00:28:41,500 Inside of this definition of my square function, 580 00:28:41,500 --> 00:28:45,730 I'm likewise, going to indent everything and say that all the square function is 581 00:28:45,730 --> 00:28:48,730 going to do is that if you hand me a number x, 582 00:28:48,730 --> 00:28:53,590 I am going to return back to you x times x, the square of the number x, 583 00:28:53,590 --> 00:28:57,770 by taking the input value and just multiplying it by itself. 584 00:28:57,770 --> 00:29:00,010 So this function, given the number two will give me 585 00:29:00,010 --> 00:29:03,370 four, if I give it number three it will give me nine, so on and so forth. 586 00:29:03,370 --> 00:29:05,380 And now on line four, I'm running a for loop. 587 00:29:05,380 --> 00:29:08,080 I'm running a loop for i in range 10. 588 00:29:08,080 --> 00:29:10,870 And if we recall what numbers is that going to range from? 589 00:29:10,870 --> 00:29:14,900 How many times will that loop run from what number to what other number? 590 00:29:14,900 --> 00:29:16,570 0 to 9, exactly. 591 00:29:16,570 --> 00:29:19,600 I start at 0, and it's going to go up to, but not including 10. 592 00:29:19,600 --> 00:29:21,430 So it'll end up stopping at 9. 593 00:29:21,430 --> 00:29:23,650 And here's what we're going to print out. 594 00:29:23,650 --> 00:29:27,950 We're going to print out something squared is something else. 595 00:29:27,950 --> 00:29:30,920 And here, I'm using this special dot format syntax. 596 00:29:30,920 --> 00:29:35,950 This is just a different way of plugging in numbers into this string, 597 00:29:35,950 --> 00:29:40,810 in particular I'm saying this is going to be a placeholder for the value i, 598 00:29:40,810 --> 00:29:44,460 and this is going to be a placeholder for the square of i. 599 00:29:44,460 --> 00:29:46,210 So whatever i's value is I want to plug it 600 00:29:46,210 --> 00:29:48,220 in to this first thing in the string. 601 00:29:48,220 --> 00:29:51,730 And the square of i is going to be plugged in to this part of the string. 602 00:29:51,730 --> 00:29:56,037 And this is a slightly older way of plugging in values into Python strings. 603 00:29:56,037 --> 00:29:58,870 And I'm showing it you here in case you ever use a version of Python 604 00:29:58,870 --> 00:30:03,280 older than 3.6 where the formatted strings, where we started strings 605 00:30:03,280 --> 00:30:05,030 with the letter f isn't supported. 606 00:30:05,030 --> 00:30:08,510 You can use this notation as well and it will effectively do the same thing. 607 00:30:08,510 --> 00:30:11,620 So in this case we're looping over the numbers from 0 to 9 608 00:30:11,620 --> 00:30:14,744 and saying something squared is something else. 609 00:30:14,744 --> 00:30:16,660 And I'm calling my square function, the square 610 00:30:16,660 --> 00:30:19,370 function that I've defined up there. 611 00:30:19,370 --> 00:30:24,510 And so when I run this program by running Python functions do 612 00:30:24,510 --> 00:30:29,410 py, what I get is a loop that runs 10 times 0 squared is 0, 1 squared is 1, 613 00:30:29,410 --> 00:30:32,080 2 squared is 4, all the way down to 9 squared 614 00:30:32,080 --> 00:30:37,150 is 81, where each time I took this input value i and called 615 00:30:37,150 --> 00:30:42,660 my square function, which gave me back a number like 81, for example. 616 00:30:42,660 --> 00:30:45,280 And this was the code to do that. 617 00:30:45,280 --> 00:30:48,280 Questions about functions or anything we've seen so far 618 00:30:48,280 --> 00:30:51,954 in the Python programming language? 619 00:30:51,954 --> 00:30:52,454 Yeah? 620 00:30:52,454 --> 00:30:55,388 AUDIENCE: Do you have to define function before you use it? 621 00:30:55,388 --> 00:30:56,855 Does it always have to go first? 622 00:30:56,855 --> 00:30:57,990 BRIAN YU: Great question. 623 00:30:57,990 --> 00:31:01,330 So the question is, do I need to define the function before I use it? 624 00:31:01,330 --> 00:31:06,200 And in general, Python needs to know about the existence of some name 625 00:31:06,200 --> 00:31:07,020 before you use it. 626 00:31:07,020 --> 00:31:09,800 So in this case, if I were to take the square function 627 00:31:09,800 --> 00:31:12,350 and move it underneath the for loop, for example, 628 00:31:12,350 --> 00:31:16,390 watch what will happen when I try and run functions do py again. 629 00:31:16,390 --> 00:31:18,137 It gives me a name error. 630 00:31:18,137 --> 00:31:19,220 This is another exception. 631 00:31:19,220 --> 00:31:20,928 We saw the index error before where I was 632 00:31:20,928 --> 00:31:24,530 trying to access some particular part of the list that wasn't supported. 633 00:31:24,530 --> 00:31:29,960 And in this case, I'm getting a name error saying square is not defined, 634 00:31:29,960 --> 00:31:32,180 meaning Python doesn't know what square is. 635 00:31:32,180 --> 00:31:34,610 And the reason is that I've hit line two, where 636 00:31:34,610 --> 00:31:38,480 I'm trying to call this square function but Python's reading my file from top 637 00:31:38,480 --> 00:31:39,330 to bottom. 638 00:31:39,330 --> 00:31:42,094 And so square as a function doesn't get defined until later on. 639 00:31:42,094 --> 00:31:45,260 So we do need it earlier, but we'll see in just a moment how we can actually 640 00:31:45,260 --> 00:31:50,270 get around that issue and actually have the square function underneath if we 641 00:31:50,270 --> 00:31:52,606 wanted to. 642 00:31:52,606 --> 00:31:53,980 So those are functions in Python. 643 00:31:53,980 --> 00:31:55,813 And the nice thing about functions in Python 644 00:31:55,813 --> 00:32:00,200 is that once you write them once in one file, you can use them in other files 645 00:32:00,200 --> 00:32:00,960 as well. 646 00:32:00,960 --> 00:32:05,189 And so you can use Python functions that you've written yourself in other files, 647 00:32:05,189 --> 00:32:07,730 and you can also use functions that other people have written 648 00:32:07,730 --> 00:32:11,540 in their own files in your own files by referring to a function that 649 00:32:11,540 --> 00:32:13,010 exists in some other file. 650 00:32:13,010 --> 00:32:15,650 So I'll show you an example of how that works. 651 00:32:15,650 --> 00:32:18,830 And this is going to be in a file called modules do py. 652 00:32:18,830 --> 00:32:22,970 And so in modules dot py what I'm doing is on line one 653 00:32:22,970 --> 00:32:26,940 I'm saying from functions import square. 654 00:32:26,940 --> 00:32:30,560 In other words, from this functions do py file that I have, 655 00:32:30,560 --> 00:32:35,300 I want to import into the file the name square, which in this case 656 00:32:35,300 --> 00:32:38,600 is a function back to modules dot py. 657 00:32:38,600 --> 00:32:43,710 From functions import a square function and then print out the square of 10. 658 00:32:43,710 --> 00:32:47,540 So I didn't explicitly define the square function inside of modules dot py, 659 00:32:47,540 --> 00:32:51,990 but I'm using it because I was able to import it from functions. 660 00:32:51,990 --> 00:32:56,550 So any guesses as to what will happen if I now run Python modules dot py? 661 00:32:56,550 --> 00:33:01,880 662 00:33:01,880 --> 00:33:05,590 Where modules the pie is importing square from functions 663 00:33:05,590 --> 00:33:08,546 and then printing out the square root of 10? 664 00:33:08,546 --> 00:33:09,670 We wanted to print out 100. 665 00:33:09,670 --> 00:33:11,170 That's what we would like to happen. 666 00:33:11,170 --> 00:33:14,580 What actually happens is that it prints out 0 squared is 0, 667 00:33:14,580 --> 00:33:16,420 1 squared is 1, so on and so forth. 668 00:33:16,420 --> 00:33:19,210 And only after all of that, then it prints out the number 100. 669 00:33:19,210 --> 00:33:22,150 So the number 100 is what we wanted, but why did the rest of the stuff 670 00:33:22,150 --> 00:33:24,181 get printed out? 671 00:33:24,181 --> 00:33:25,522 AUDIENCE: It executes still. 672 00:33:25,522 --> 00:33:29,170 BRIAN YU: Yeah, it executed this code that was originally inside of functions 673 00:33:29,170 --> 00:33:33,260 do py, this for loop that I defined alongside the square function. 674 00:33:33,260 --> 00:33:37,000 And the reason why is that when I tried to import from this function's file, 675 00:33:37,000 --> 00:33:39,670 it went through the function's file going through each line. 676 00:33:39,670 --> 00:33:41,378 And when it hit that for loop, it decided 677 00:33:41,378 --> 00:33:43,030 to just run that for loop for me. 678 00:33:43,030 --> 00:33:45,400 And so that's probably not quite what I want to happen. 679 00:33:45,400 --> 00:33:49,150 I would like for someone to be able to import the square function 680 00:33:49,150 --> 00:33:51,790 from my functions file without them needing 681 00:33:51,790 --> 00:33:57,100 to then run all of the code inside of the main part of my functions 682 00:33:57,100 --> 00:33:59,180 file automatically. 683 00:33:59,180 --> 00:34:02,860 And so one common solution to this in Python is to put all of the code 684 00:34:02,860 --> 00:34:06,730 that I want to run only when I actually run this functions file inside 685 00:34:06,730 --> 00:34:07,900 of its own function. 686 00:34:07,900 --> 00:34:09,940 And this is generally called a main function, 687 00:34:09,940 --> 00:34:12,190 which will be just the main function that runs 688 00:34:12,190 --> 00:34:14,760 when I try and run functions dot py. 689 00:34:14,760 --> 00:34:16,510 I've taken everything and I've indented it 690 00:34:16,510 --> 00:34:20,014 to say this is all code that's going to be inside of the main function. 691 00:34:20,014 --> 00:34:22,389 And then the last thing I need is a bit of special syntax 692 00:34:22,389 --> 00:34:24,280 that you don't need to worry about too much. 693 00:34:24,280 --> 00:34:30,429 But effectively what I'm saying here is if name equals main-- 694 00:34:30,429 --> 00:34:34,669 in other words, if I am currently running this particular file, 695 00:34:34,669 --> 00:34:36,460 that's how you should interpret that line-- 696 00:34:36,460 --> 00:34:39,026 then run the main function. 697 00:34:39,026 --> 00:34:40,900 And so it's a little bit of added complexity. 698 00:34:40,900 --> 00:34:43,270 But the reason for this added complexity is 699 00:34:43,270 --> 00:34:47,170 that now when I run the functions dot py, 700 00:34:47,170 --> 00:34:51,070 I still get 0 through 9 printed out just as normal like I want to. 701 00:34:51,070 --> 00:34:55,000 But if I run modules dot py, the one that was importing the square function 702 00:34:55,000 --> 00:34:57,050 and then just calling the square root of 10-- 703 00:34:57,050 --> 00:34:57,550 oops. 704 00:34:57,550 --> 00:34:59,590 Python modules dot py-- 705 00:34:59,590 --> 00:35:02,980 then what I get is just the number 100 because that 706 00:35:02,980 --> 00:35:05,590 is the result of calling square on the number 10. 707 00:35:05,590 --> 00:35:08,110 And it didn't call any of this code. 708 00:35:08,110 --> 00:35:11,380 It didn't run any of the code that was only inside of the main function. 709 00:35:11,380 --> 00:35:16,180 It only ran the code that was explicitly asked to be run, which in this case, 710 00:35:16,180 --> 00:35:18,530 was calling for the square of 10. 711 00:35:18,530 --> 00:35:22,930 So that was an example of how we can import functions from other places 712 00:35:22,930 --> 00:35:23,950 in order to use them. 713 00:35:23,950 --> 00:35:27,430 And we'll soon see when we start moving to web development 714 00:35:27,430 --> 00:35:29,710 and writing web applications in Python, that this 715 00:35:29,710 --> 00:35:31,750 will be really important for us, that there are functions that 716 00:35:31,750 --> 00:35:35,041 do things in web applications that other people have written that we would like 717 00:35:35,041 --> 00:35:37,120 to use, that we can import from other people 718 00:35:37,120 --> 00:35:39,667 that they have written without needing to write it ourselves. 719 00:35:39,667 --> 00:35:41,500 And we can take advantage of those functions 720 00:35:41,500 --> 00:35:43,875 and effectively stand on the shoulders of others in order 721 00:35:43,875 --> 00:35:49,600 to build web applications that take advantage of those existing features. 722 00:35:49,600 --> 00:35:52,750 Questions about anything else before we look at one last feature of Python, 723 00:35:52,750 --> 00:35:56,980 before diving back into web programming? 724 00:35:56,980 --> 00:35:59,630 Last thing we'll take a look at is Python classes. 725 00:35:59,630 --> 00:36:02,380 And so this is something that will become more relevant next week. 726 00:36:02,380 --> 00:36:04,660 But we're going to take a look at it now just to get a preview and a taste 727 00:36:04,660 --> 00:36:05,740 for what it's like. 728 00:36:05,740 --> 00:36:10,180 Python classes are a way of defining entirely new types in Python. 729 00:36:10,180 --> 00:36:13,522 So Python has a built in type for representing lists. 730 00:36:13,522 --> 00:36:14,980 It has a built in type for strings. 731 00:36:14,980 --> 00:36:16,960 It has a built in type for Boolean values, 732 00:36:16,960 --> 00:36:21,280 but it doesn't have a built in type for representing a point in space. 733 00:36:21,280 --> 00:36:23,500 We could use a tuple, of course, like we saw before, 734 00:36:23,500 --> 00:36:25,850 just some number comma some other value. 735 00:36:25,850 --> 00:36:27,970 But here is a way of me explicitly creating 736 00:36:27,970 --> 00:36:30,460 a new type in Python called a point. 737 00:36:30,460 --> 00:36:32,500 And here's the way it works. 738 00:36:32,500 --> 00:36:37,000 So on line one I'm saying I'm defining a new class of things called points. 739 00:36:37,000 --> 00:36:40,300 And on line two I have this special init function. 740 00:36:40,300 --> 00:36:42,640 And the init function in Python is a way of saying 741 00:36:42,640 --> 00:36:46,390 when I create a new point, what information do I need? 742 00:36:46,390 --> 00:36:49,360 And in particular, I need self, which is just 743 00:36:49,360 --> 00:36:52,720 going to be a variable that represents the point itself, 744 00:36:52,720 --> 00:36:57,620 the object that I'm creating, and then I need an x value and a y value. 745 00:36:57,620 --> 00:37:00,910 And so when I create a new point, what should I do? 746 00:37:00,910 --> 00:37:04,780 Self dot x equals x is my way of saying self 747 00:37:04,780 --> 00:37:08,770 is that name, referring to the point object that I've just created. 748 00:37:08,770 --> 00:37:11,980 And dot x is my way of saying, I want to access 749 00:37:11,980 --> 00:37:16,810 a particular attribute of the self, of the point that I've created. 750 00:37:16,810 --> 00:37:21,080 In particular, I want to set self x attribute to whatever 751 00:37:21,080 --> 00:37:23,290 this x value is that's being passed in. 752 00:37:23,290 --> 00:37:28,150 That way, when I create a new point, I'm storing that x value inside of self 753 00:37:28,150 --> 00:37:29,290 dot x. 754 00:37:29,290 --> 00:37:34,660 And likewise, I'm storing the y value of the point inside of self dot y. 755 00:37:34,660 --> 00:37:38,350 And so when I actually use this is on something like line six where I say p 756 00:37:38,350 --> 00:37:41,770 is equal to point 3,5. 757 00:37:41,770 --> 00:37:44,230 That is going to create a brand new point, 758 00:37:44,230 --> 00:37:48,370 calling this init function that gets called anytime it create a new point. 759 00:37:48,370 --> 00:37:52,000 And it's going to set p's x value to be whatever 760 00:37:52,000 --> 00:37:57,100 get passed in at x, which is 3, and set p's y value to be whatever was passed 761 00:37:57,100 --> 00:37:59,740 in as the y value, in this case 5. 762 00:37:59,740 --> 00:38:03,530 And now if I print out p.x and p.y, that's 763 00:38:03,530 --> 00:38:08,120 going to take this point to object and access whatever its x attribute is 764 00:38:08,120 --> 00:38:12,410 and whatever its y's attribute is and print out those values. 765 00:38:12,410 --> 00:38:14,750 And so we'll take a look at that. 766 00:38:14,750 --> 00:38:19,580 If I run the classes dot py and press Return, what I get 767 00:38:19,580 --> 00:38:22,700 is 3 on the first line and then 5 on the next line. 768 00:38:22,700 --> 00:38:26,780 Because I first decided to print out the x value of my point p. 769 00:38:26,780 --> 00:38:30,430 And after that, decided to print out the y value of my point p as well. 770 00:38:30,430 --> 00:38:35,000 And so that printed out 3 as the x value and 5 as the y value. 771 00:38:35,000 --> 00:38:38,360 And so that would be how we would create classes entirely new types in Python 772 00:38:38,360 --> 00:38:39,200 as well. 773 00:38:39,200 --> 00:38:42,417 And so that was a lot of overview of the Python programming language. 774 00:38:42,417 --> 00:38:43,250 It's a big language. 775 00:38:43,250 --> 00:38:44,380 There's a lot of stuff going on. 776 00:38:44,380 --> 00:38:46,713 We looked at different types of variables and data types 777 00:38:46,713 --> 00:38:49,220 and conditions and loops and functions and classes. 778 00:38:49,220 --> 00:38:52,400 Totally OK if this is all new to you, but hopefully some of the concepts 779 00:38:52,400 --> 00:38:54,650 seem familiar or reminiscent of programming languages 780 00:38:54,650 --> 00:38:56,666 that you may have used before. 781 00:38:56,666 --> 00:38:58,040 But we'll take a short break now. 782 00:38:58,040 --> 00:38:59,660 And after we come back from the break, we'll 783 00:38:59,660 --> 00:39:02,450 talk about how to begin to use some of these language features 784 00:39:02,450 --> 00:39:04,910 in order to actually build web applications that 785 00:39:04,910 --> 00:39:06,200 are living on the internet. 786 00:39:06,200 --> 00:39:09,199 So we'll take a short break and then we'll come back. 787 00:39:09,199 --> 00:39:09,740 Welcome back. 788 00:39:09,740 --> 00:39:12,531 So we just got a whirlwind tour of the Python programming language. 789 00:39:12,531 --> 00:39:14,990 And now what we're going to do is use Python to begin 790 00:39:14,990 --> 00:39:17,270 to build some dynamic web applications. 791 00:39:17,270 --> 00:39:19,853 And so before we get there, I just want to take a brief moment 792 00:39:19,853 --> 00:39:21,416 to talk about HTTP. 793 00:39:21,416 --> 00:39:24,320 HTTP, hypertext transfer protocol, which is the system 794 00:39:24,320 --> 00:39:26,903 that we're going to be using that the website and the internet 795 00:39:26,903 --> 00:39:29,930 uses in order to interact and communicate 796 00:39:29,930 --> 00:39:31,700 between computers and servers. 797 00:39:31,700 --> 00:39:34,190 And so the general idea or the model to get in your head 798 00:39:34,190 --> 00:39:37,280 is that when you type in a website and press Return, what that's doing 799 00:39:37,280 --> 00:39:39,710 is sending an HTTP request to some server. 800 00:39:39,710 --> 00:39:41,960 If I type google.com and press Return, I'm 801 00:39:41,960 --> 00:39:44,990 sending an HTTP request to Google's server. 802 00:39:44,990 --> 00:39:47,630 Google's server receives that request, needs to figure out 803 00:39:47,630 --> 00:39:49,125 some way to interpret that request. 804 00:39:49,125 --> 00:39:50,000 What am I asking for? 805 00:39:50,000 --> 00:39:51,000 What am I searching for? 806 00:39:51,000 --> 00:39:53,720 Am I searching for news or images or something else? 807 00:39:53,720 --> 00:39:55,846 It figures out what's going on in that request. 808 00:39:55,846 --> 00:39:58,220 Figures out what information to give back to me, and then 809 00:39:58,220 --> 00:40:02,210 sends me back and HTTP response that contains the information that my web 810 00:40:02,210 --> 00:40:06,950 browser then receives and then displays on a page in Chrome or Safari 811 00:40:06,950 --> 00:40:09,156 or whatever web browser that it happen to be using. 812 00:40:09,156 --> 00:40:11,030 And so what we're going to be doing now as we 813 00:40:11,030 --> 00:40:14,450 go about building web applications, is writing 814 00:40:14,450 --> 00:40:17,019 code that will take care of that server side processing. 815 00:40:17,019 --> 00:40:20,060 Receiving requests, figuring out what those requests they're dealing with 816 00:40:20,060 --> 00:40:23,210 and what they're asking for, and figuring out what response to then 817 00:40:23,210 --> 00:40:25,200 give back to the user. 818 00:40:25,200 --> 00:40:27,650 And in order to do that, we're going to be using flask. 819 00:40:27,650 --> 00:40:31,460 Flask as a micro framework written in Python. 820 00:40:31,460 --> 00:40:33,470 What that effectively means is that flask 821 00:40:33,470 --> 00:40:37,100 is some code already written for us in Python that makes it easy to get up 822 00:40:37,100 --> 00:40:39,050 and running with a simple web application that 823 00:40:39,050 --> 00:40:42,050 has a lot of features that can be useful as we go about developing web 824 00:40:42,050 --> 00:40:44,340 applications, as we'll soon see in a moment. 825 00:40:44,340 --> 00:40:47,720 And so flask makes the process of designing a web application relatively 826 00:40:47,720 --> 00:40:50,870 easy, and lets us focus really on what users 827 00:40:50,870 --> 00:40:53,150 are requesting and what sort of response that we 828 00:40:53,150 --> 00:40:57,150 want to provide back to the user after that request has been made. 829 00:40:57,150 --> 00:41:02,120 So let's take a brief look at a first web application in flask. 830 00:41:02,120 --> 00:41:05,210 And this is going to be inside of the first directory. 831 00:41:05,210 --> 00:41:09,740 And so flask code is generally stored inside of a file 832 00:41:09,740 --> 00:41:14,490 called application dot py is going to be the main file of a flask application. 833 00:41:14,490 --> 00:41:18,620 And here is the code that we need in order to run this flask application, 834 00:41:18,620 --> 00:41:20,600 in order to run a basic web application that we 835 00:41:20,600 --> 00:41:22,940 can serve as if it were a website. 836 00:41:22,940 --> 00:41:26,090 So on line one we have from flask import flask. 837 00:41:26,090 --> 00:41:29,360 Just like before, when we were importing that square function 838 00:41:29,360 --> 00:41:32,660 from the other file that I had created, here we're 839 00:41:32,660 --> 00:41:35,270 importing flask, which is just going to be 840 00:41:35,270 --> 00:41:39,694 a way of creating a flask web server from this flask module that 841 00:41:39,694 --> 00:41:40,610 exists somewhere else. 842 00:41:40,610 --> 00:41:42,350 Someone else wrote the flask module. 843 00:41:42,350 --> 00:41:43,830 You can install it for free. 844 00:41:43,830 --> 00:41:47,150 And what we're doing on line one is just saying that in this Python file, 845 00:41:47,150 --> 00:41:49,564 we want to use that flask module. 846 00:41:49,564 --> 00:41:50,480 Now what are we doing? 847 00:41:50,480 --> 00:41:53,355 On line three-- this extra line is just there for aesthetic purposes. 848 00:41:53,355 --> 00:41:54,770 It doesn't serve a real purpose-- 849 00:41:54,770 --> 00:41:58,490 we're saying app is equal to flask underscore, underscore name 850 00:41:58,490 --> 00:42:00,000 underscore, underscore. 851 00:42:00,000 --> 00:42:03,710 And what that's doing is saying I want to create a new web application. 852 00:42:03,710 --> 00:42:07,040 And I want this web application to be a flask web application, 853 00:42:07,040 --> 00:42:10,340 where underscore, underscore a name is just representing this current file, 854 00:42:10,340 --> 00:42:13,830 that this file is going to represent my web application. 855 00:42:13,830 --> 00:42:16,760 Then on line five, this is where things get interesting. 856 00:42:16,760 --> 00:42:20,720 At app dot route and then slash. 857 00:42:20,720 --> 00:42:24,620 So flask is designed in terms of routes, where a route is just 858 00:42:24,620 --> 00:42:27,920 part of the URL you type in order to determine 859 00:42:27,920 --> 00:42:29,690 which page you want to request. 860 00:42:29,690 --> 00:42:32,790 And so this slash just represents the default page. 861 00:42:32,790 --> 00:42:35,965 If I go to a website slash and then nothing else after the flash, 862 00:42:35,965 --> 00:42:38,090 that is the default page of the website that I just 863 00:42:38,090 --> 00:42:42,370 want to access when I access the web page for the first time, for instance. 864 00:42:42,370 --> 00:42:45,530 And what line five is saying, app dot route slash, 865 00:42:45,530 --> 00:42:48,800 is that when the user goes to just slash on my website, 866 00:42:48,800 --> 00:42:52,700 goes to that default route, the function immediately below it 867 00:42:52,700 --> 00:42:54,290 is the function that I want to run. 868 00:42:54,290 --> 00:42:56,150 This is a special line called a decorator. 869 00:42:56,150 --> 00:42:58,590 No need to worry too much about exactly how that works. 870 00:42:58,590 --> 00:43:01,300 But the idea is that I am tying this function immediately 871 00:43:01,300 --> 00:43:06,970 underneath app dot route slash to this slash, so that when I go to slash 872 00:43:06,970 --> 00:43:08,890 is the function that's going to run. 873 00:43:08,890 --> 00:43:10,990 This is a Python function just called index. 874 00:43:10,990 --> 00:43:14,380 And all my index function is doing is returning the string 875 00:43:14,380 --> 00:43:17,110 hello world, just returning that text. 876 00:43:17,110 --> 00:43:21,790 So this is a very simple seven line web application written in Python. 877 00:43:21,790 --> 00:43:23,620 And let's try and run it now. 878 00:43:23,620 --> 00:43:28,600 So in order to run a flask application, I'm going to go into the directory 879 00:43:28,600 --> 00:43:31,450 where that application is located, in this case, it's called first. 880 00:43:31,450 --> 00:43:36,340 And I'm going to run flask run, where flask is a web server that I'm going 881 00:43:36,340 --> 00:43:39,170 to just run in this current directory. 882 00:43:39,170 --> 00:43:40,600 So I type flask run. 883 00:43:40,600 --> 00:43:44,170 And what I get is I'm now serving the flask app application. 884 00:43:44,170 --> 00:43:47,780 And I'm running it on this particular URL. 885 00:43:47,780 --> 00:43:53,590 And so if I take this URL and paste it into a web browser for instance, what 886 00:43:53,590 --> 00:43:56,530 I get is just the words hello world. 887 00:43:56,530 --> 00:43:58,420 I went to the default route on my website. 888 00:43:58,420 --> 00:43:59,950 I just pressed Return. 889 00:43:59,950 --> 00:44:02,860 And the result is that this text is what came back to me. 890 00:44:02,860 --> 00:44:04,930 This is the response that flask produced. 891 00:44:04,930 --> 00:44:09,100 And it was produced because of this line, this return hello world 892 00:44:09,100 --> 00:44:14,680 line, that happened whenever someone went to the slash route on my website. 893 00:44:14,680 --> 00:44:18,160 If this had instead been hello world with extra exclamation 894 00:44:18,160 --> 00:44:21,980 points for instance-- if I save that, and I refresh the page, 895 00:44:21,980 --> 00:44:23,920 now those extra exclamation points appear. 896 00:44:23,920 --> 00:44:26,350 So by editing my Python code, this flask code, 897 00:44:26,350 --> 00:44:29,530 that I'm able to change the way that my website looks. 898 00:44:29,530 --> 00:44:32,349 Questions about that very simple first web application 899 00:44:32,349 --> 00:44:34,390 that we've been able to create with just a couple 900 00:44:34,390 --> 00:44:36,560 of lines of code using Python and flask? 901 00:44:36,560 --> 00:44:37,060 Yeah? 902 00:44:37,060 --> 00:44:40,497 AUDIENCE: Does flask know to look for a file callled application dot py? 903 00:44:40,497 --> 00:44:41,590 BRIAN YU: Great question. 904 00:44:41,590 --> 00:44:44,860 Does flask know to look for an application called application dot py? 905 00:44:44,860 --> 00:44:46,300 Not out of the box necessarily. 906 00:44:46,300 --> 00:44:50,260 So what might happen is if you try and just run a flask run, 907 00:44:50,260 --> 00:44:53,980 you might get an error that says flask doesn't know where to look 908 00:44:53,980 --> 00:44:55,840 for your particular application. 909 00:44:55,840 --> 00:44:58,900 And the reason why is that flask relies on what's 910 00:44:58,900 --> 00:45:01,900 called an environment variable, a variable that's set inside 911 00:45:01,900 --> 00:45:05,080 of your terminal to know what file to be looking 912 00:45:05,080 --> 00:45:07,270 for as the source of the application. 913 00:45:07,270 --> 00:45:11,410 I've already sent my application to be application dot py. 914 00:45:11,410 --> 00:45:13,310 But if you're running for the first time, 915 00:45:13,310 --> 00:45:16,090 you might need a line like export flask underscore 916 00:45:16,090 --> 00:45:18,730 app equals application dot py. 917 00:45:18,730 --> 00:45:23,050 And all that line is doing is saying set the environment variable flask 918 00:45:23,050 --> 00:45:25,240 app to be application dot py. 919 00:45:25,240 --> 00:45:27,790 In other words, tell flask that the file that I 920 00:45:27,790 --> 00:45:29,890 want to run this application from is a file 921 00:45:29,890 --> 00:45:33,470 called application do py, which is just the general convention. 922 00:45:33,470 --> 00:45:35,359 But depending upon what system you're using, 923 00:45:35,359 --> 00:45:37,400 that may or may not be set automatically for you. 924 00:45:37,400 --> 00:45:39,890 So you may need to explicitly tell flask application 925 00:45:39,890 --> 00:45:41,457 do py is what you want to use. 926 00:45:41,457 --> 00:45:42,040 Good question. 927 00:45:42,040 --> 00:45:47,992 AUDIENCE: So was it the line that said [INAUDIBLE] 928 00:45:47,992 --> 00:45:50,472 or was it environment variable? 929 00:45:50,472 --> 00:45:52,000 BRIAN YU: Good question. 930 00:45:52,000 --> 00:45:54,460 So did I not have to do that? 931 00:45:54,460 --> 00:45:58,530 I have my terminal configured such that it will automatically run that line. 932 00:45:58,530 --> 00:46:00,930 It will automatically set the environment variable. 933 00:46:00,930 --> 00:46:03,430 And we can give you instructions for how to do that as well. 934 00:46:03,430 --> 00:46:07,584 But otherwise, you can just need to set the environment variable yourself. 935 00:46:07,584 --> 00:46:11,000 AUDIENCE: But there's also y in the-- 936 00:46:11,000 --> 00:46:18,320 the application up higher that said app equals [INAUDIBLE] 937 00:46:18,320 --> 00:46:19,370 BRIAN YU: Good question. 938 00:46:19,370 --> 00:46:20,552 So what's this line doing? 939 00:46:20,552 --> 00:46:22,760 So all this line is doing is it doesn't have anything 940 00:46:22,760 --> 00:46:27,860 to do with telling flask which application to run. 941 00:46:27,860 --> 00:46:30,800 This is just us creating a new variable that 942 00:46:30,800 --> 00:46:35,750 is going to be the source of this web application called app such that later 943 00:46:35,750 --> 00:46:38,130 I can tie specific functions to it. 944 00:46:38,130 --> 00:46:41,210 So I created this flask variable called app. 945 00:46:41,210 --> 00:46:43,730 And using that app, I'm now able to say when 946 00:46:43,730 --> 00:46:47,060 someone goes to this route this is the function that I want to run. 947 00:46:47,060 --> 00:46:48,860 And it it's only used inside of this file 948 00:46:48,860 --> 00:46:53,630 to determine what routes get called and what functions get called as a result. 949 00:46:53,630 --> 00:46:55,430 Good questions though. 950 00:46:55,430 --> 00:46:57,430 So that was our first web application. 951 00:46:57,430 --> 00:47:00,440 It just returned some basic text when we go to the web application. 952 00:47:00,440 --> 00:47:02,780 But that's not all quite all that interesting just yet. 953 00:47:02,780 --> 00:47:07,340 So let's try and make things a little more interesting, in particular, 954 00:47:07,340 --> 00:47:10,680 let's try and add a couple routes. 955 00:47:10,680 --> 00:47:14,780 So let's go into routes 0 and take a look at this code. 956 00:47:14,780 --> 00:47:19,400 So inside of application dot py here, we see that up until line 957 00:47:19,400 --> 00:47:20,840 seven everything is identical. 958 00:47:20,840 --> 00:47:22,400 I had app route slash. 959 00:47:22,400 --> 00:47:25,040 And when that happens, I want to run this index function that 960 00:47:25,040 --> 00:47:27,440 just returns the text hello world. 961 00:47:27,440 --> 00:47:30,110 But here on line nine I've added a special additional route, 962 00:47:30,110 --> 00:47:32,420 app dot route slash David. 963 00:47:32,420 --> 00:47:34,790 And when I go to slash David on my web application, 964 00:47:34,790 --> 00:47:36,860 it's going to call this David function. 965 00:47:36,860 --> 00:47:39,800 And what that does is return the words hello David. 966 00:47:39,800 --> 00:47:44,150 So what's the result of that going to be when I run my flask application? 967 00:47:44,150 --> 00:47:46,850 Well, if I run flask run and then go back 968 00:47:46,850 --> 00:47:50,156 to this URL, this local URL just on my website, 969 00:47:50,156 --> 00:47:51,530 it just says hello world for now. 970 00:47:51,530 --> 00:47:53,750 It just shows me that default route. 971 00:47:53,750 --> 00:47:57,740 But if I go into my URL bar and change the URL from just the default 972 00:47:57,740 --> 00:48:03,110 route to this URL slash David, for example and press Return there, 973 00:48:03,110 --> 00:48:04,434 now it changes to hello David. 974 00:48:04,434 --> 00:48:07,100 So I have two separate routes now running on my web application. 975 00:48:07,100 --> 00:48:09,950 If I just go to the default route, it says hello world. 976 00:48:09,950 --> 00:48:13,790 If I go to slash David, then it says hello David. 977 00:48:13,790 --> 00:48:17,300 And that's all because using flask I was able to tie 978 00:48:17,300 --> 00:48:21,950 specific functions to particular routes of my web application. 979 00:48:21,950 --> 00:48:27,084 Questions about how that's been able to work so far? 980 00:48:27,084 --> 00:48:29,750 So if I wanted to add additional routes to do additional things, 981 00:48:29,750 --> 00:48:30,833 I could certainly do that. 982 00:48:30,833 --> 00:48:34,490 If I wanted to add a different route to say hello to Maria, for example, 983 00:48:34,490 --> 00:48:37,090 I could add another line that app dot route 984 00:48:37,090 --> 00:48:40,640 slash Maria, define a new function called Maria, in which case, 985 00:48:40,640 --> 00:48:43,730 I would return hello Maria. 986 00:48:43,730 --> 00:48:45,170 And now if I run-- 987 00:48:45,170 --> 00:48:47,662 go to slash Maria on my website, it's going 988 00:48:47,662 --> 00:48:50,120 to say hello Maria, because I've added that additional one. 989 00:48:50,120 --> 00:48:52,245 But of course, this isn't going to work for anyone. 990 00:48:52,245 --> 00:48:54,380 If I try and type my own name, slash Brian, 991 00:48:54,380 --> 00:48:58,070 I get a not found error because I've typed in a route, 992 00:48:58,070 --> 00:49:01,550 but my flask application doesn't know how to deal with that route yet. 993 00:49:01,550 --> 00:49:04,670 It doesn't know how to deal with my name Brian, because I only 994 00:49:04,670 --> 00:49:08,520 have routes for the default route, the slash David route, and the slash Maria 995 00:49:08,520 --> 00:49:09,020 route. 996 00:49:09,020 --> 00:49:10,340 My name isn't one of them. 997 00:49:10,340 --> 00:49:15,170 So what if I want to make my flask application a little more powerful, 998 00:49:15,170 --> 00:49:19,220 and let it say hello to anyone, not just David and not just Maria? 999 00:49:19,220 --> 00:49:28,820 Let's take a look now at routes 1, which will be an example of just that. 1000 00:49:28,820 --> 00:49:32,401 So inside of application dot py here's what we have going on inside of routes 1001 00:49:32,401 --> 00:49:32,900 1. 1002 00:49:32,900 --> 00:49:34,820 Up until line 7, everything is identical. 1003 00:49:34,820 --> 00:49:37,700 We're just saying hello world if I go to the default slash route. 1004 00:49:37,700 --> 00:49:41,270 But where things get interesting is down here line 9. 1005 00:49:41,270 --> 00:49:47,030 I have app dot route slash, and then in angled brackets string colon name. 1006 00:49:47,030 --> 00:49:49,670 This is not a particular route that someone is going to, 1007 00:49:49,670 --> 00:49:53,090 but a template for a whole generalized set of routes 1008 00:49:53,090 --> 00:49:55,940 that people could potentially go for it such that whenever anyone 1009 00:49:55,940 --> 00:49:58,850 goes to slash and then any string-- 1010 00:49:58,850 --> 00:50:01,010 and we're going to call that string name-- 1011 00:50:01,010 --> 00:50:03,190 it's going to call this hello function. 1012 00:50:03,190 --> 00:50:05,490 And this hello function takes as an argument 1013 00:50:05,490 --> 00:50:08,990 this name, a name that gets passed in via the URL 1014 00:50:08,990 --> 00:50:11,220 that the user typed into their web browser. 1015 00:50:11,220 --> 00:50:12,170 And what happens here? 1016 00:50:12,170 --> 00:50:16,160 Well, I'm going to return this formatted string hello comma, 1017 00:50:16,160 --> 00:50:20,660 and then name in the curly braces, which is very reminiscent of one 1018 00:50:20,660 --> 00:50:22,910 of those early Python files that we looked at way back 1019 00:50:22,910 --> 00:50:25,160 at the beginning of lecture where I asked for a name 1020 00:50:25,160 --> 00:50:29,360 to be typed in just at the command line and then printed out hello name. 1021 00:50:29,360 --> 00:50:33,500 This is exactly the same line, but it's contained inside of one of these flask 1022 00:50:33,500 --> 00:50:36,500 routes now such that this route is going to capture 1023 00:50:36,500 --> 00:50:41,570 any string that I type in as a name instead of just David or just Maria. 1024 00:50:41,570 --> 00:50:48,470 So if I now head over here and run this application by typing flask run, 1025 00:50:48,470 --> 00:50:52,610 and now I go to just the default route, it says hello world. 1026 00:50:52,610 --> 00:50:56,360 But if I instead go to slash David, it says hello David. 1027 00:50:56,360 --> 00:50:58,430 I go to slash Maria, it says hello Maria. 1028 00:50:58,430 --> 00:51:00,470 And I go to slash Brian, it says hello Brian. 1029 00:51:00,470 --> 00:51:04,460 It's able to take any string that I type in, 1030 00:51:04,460 --> 00:51:06,777 and just return hello to whoever that is. 1031 00:51:06,777 --> 00:51:09,360 So I've already been able to create a dynamic web application. 1032 00:51:09,360 --> 00:51:13,400 I didn't have to create a separate HTML web page for each different person 1033 00:51:13,400 --> 00:51:14,900 that I would want to say hello to. 1034 00:51:14,900 --> 00:51:17,040 Just depending upon what's passed into the URL, 1035 00:51:17,040 --> 00:51:20,030 I'm now able to create a dynamic web application that can say hello 1036 00:51:20,030 --> 00:51:22,310 to anyone, hypothetically. 1037 00:51:22,310 --> 00:51:25,650 And the beauty of this is that this is all just Python code. 1038 00:51:25,650 --> 00:51:29,390 So anything you can do in Python, you can edit application dot py 1039 00:51:29,390 --> 00:51:33,140 to reflect the changes in order to update the website 1040 00:51:33,140 --> 00:51:35,970 or update values of things to be whatever you want them to be. 1041 00:51:35,970 --> 00:51:39,430 So for instance, Python strings have a method, 1042 00:51:39,430 --> 00:51:42,830 a function that you can call upon them called capitalize that takes a name 1043 00:51:42,830 --> 00:51:45,440 and capitalizes the first letter of it, for example. 1044 00:51:45,440 --> 00:51:51,040 So if I, in my hello function, just said name equals name dot capitalize, 1045 00:51:51,040 --> 00:51:54,920 what that's going to do is that if I type in a name that's the URL, 1046 00:51:54,920 --> 00:51:59,870 it's going to first capitalize that name and then return hello that name. 1047 00:51:59,870 --> 00:52:03,320 So before I type in slash Brian, it said hello brian with a lowercase b. 1048 00:52:03,320 --> 00:52:06,500 I refresh the page now, now the B is capitalized 1049 00:52:06,500 --> 00:52:11,150 because I've added this line 11 that just capitalizes that name for you 1050 00:52:11,150 --> 00:52:14,330 before returning it back to the user. 1051 00:52:14,330 --> 00:52:20,810 Questions about routes that we've seen so far in flask? 1052 00:52:20,810 --> 00:52:22,360 Or how the applications work? 1053 00:52:22,360 --> 00:52:25,740 1054 00:52:25,740 --> 00:52:29,457 Let's take a look at some of the other features that we can have in flask. 1055 00:52:29,457 --> 00:52:31,290 And the first thing that we'll probably note 1056 00:52:31,290 --> 00:52:34,750 is that these web pages are very, very simple so far. 1057 00:52:34,750 --> 00:52:38,370 Right now all they do is display some basic text. 1058 00:52:38,370 --> 00:52:42,570 And of course, we could add whatever HTML that we want to this. 1059 00:52:42,570 --> 00:52:47,160 If I wanted hello Brian to be a heading for example, instead of just plain 1060 00:52:47,160 --> 00:52:53,160 text, I could return instead of hello name, like, H1 and then slash H1. 1061 00:52:53,160 --> 00:52:55,590 If we recall from the HTML lecture, H1 is 1062 00:52:55,590 --> 00:52:59,240 a way of making a big bold heading at the top of the page. 1063 00:52:59,240 --> 00:53:03,930 And so if I return those H1 tags surrounding hello name, 1064 00:53:03,930 --> 00:53:06,690 now I when I refresh this page, hello Brian appears big and bold. 1065 00:53:06,690 --> 00:53:09,750 I'm able to use whatever HTML content I want in order 1066 00:53:09,750 --> 00:53:13,110 to return that information back to the user when they see it 1067 00:53:13,110 --> 00:53:14,220 in their web browser. 1068 00:53:14,220 --> 00:53:19,009 But of course, the HTML pages that you guys created in project 0 or HTML pages 1069 00:53:19,009 --> 00:53:22,050 you might have created in other contexts are likely much more complicated 1070 00:53:22,050 --> 00:53:24,977 than what could reasonably fit in just a single string. 1071 00:53:24,977 --> 00:53:26,310 You can make it very, very long. 1072 00:53:26,310 --> 00:53:28,360 But that's quickly going to start to get messy. 1073 00:53:28,360 --> 00:53:32,830 So what we want to do is organize our flask application such that we can put 1074 00:53:32,830 --> 00:53:37,950 HTML in HTML files, .html files just like you were using for project 0, 1075 00:53:37,950 --> 00:53:40,800 but somehow tie those html files into flask. 1076 00:53:40,800 --> 00:53:45,510 Tell flask to use those html files that we've already created in order 1077 00:53:45,510 --> 00:53:49,480 to return something back to the user. 1078 00:53:49,480 --> 00:53:53,145 So let's take a look now at another example. 1079 00:53:53,145 --> 00:53:56,410 1080 00:53:56,410 --> 00:54:01,620 Here, inside of application .html, here is what we have going on. 1081 00:54:01,620 --> 00:54:03,120 From flask we import flask. 1082 00:54:03,120 --> 00:54:04,820 And we're also importing a second thing. 1083 00:54:04,820 --> 00:54:06,570 In addition to just importing flask, we're 1084 00:54:06,570 --> 00:54:09,870 importing a function in a flask called render template. 1085 00:54:09,870 --> 00:54:12,900 And we'll see why that's going to become useful in just a moment. 1086 00:54:12,900 --> 00:54:15,060 Line 3 is exactly the same so far. 1087 00:54:15,060 --> 00:54:17,790 We just have app equals flask name. 1088 00:54:17,790 --> 00:54:21,030 Then on line 5 we create our default route, app.route slash, 1089 00:54:21,030 --> 00:54:22,530 then the index function. 1090 00:54:22,530 --> 00:54:24,960 And instead of returning a string, just text 1091 00:54:24,960 --> 00:54:27,740 that we want to display to the user, I'm returning 1092 00:54:27,740 --> 00:54:31,490 render template and then index.html. 1093 00:54:31,490 --> 00:54:36,150 And what that's telling flask to do is take an index.html file 1094 00:54:36,150 --> 00:54:38,430 and render that and display it to the user 1095 00:54:38,430 --> 00:54:42,520 instead of just displaying text, plain text. 1096 00:54:42,520 --> 00:54:45,510 So if you look at the structure of where I 1097 00:54:45,510 --> 00:54:50,410 have my files, in the same folder that I have my application.py file 1098 00:54:50,410 --> 00:54:52,710 I also have this templates directory. 1099 00:54:52,710 --> 00:54:57,190 And inside of this templates directory I have a document called index.html. 1100 00:54:57,190 --> 00:55:01,860 And if I open up index.html, here's what it looks like. 1101 00:55:01,860 --> 00:55:06,420 It looks like an HTML file that's got a title that says my web page. 1102 00:55:06,420 --> 00:55:10,920 And inside the body it just says hello world. 1103 00:55:10,920 --> 00:55:17,040 So what will now happen if I try and run this web application? 1104 00:55:17,040 --> 00:55:19,530 I go to that URL, and now it displays hello world. 1105 00:55:19,530 --> 00:55:22,740 And if I click and view the page source of this web page, 1106 00:55:22,740 --> 00:55:27,180 I can see the html content to that web page is the same as index.html. 1107 00:55:27,180 --> 00:55:30,360 So what I've effectively done here is, via a round about way 1108 00:55:30,360 --> 00:55:33,210 using flask and Python, allowed us to just display 1109 00:55:33,210 --> 00:55:36,300 an HTML page in the same way that you've been doing already, 1110 00:55:36,300 --> 00:55:38,820 just by writing the contents into the html itself 1111 00:55:38,820 --> 00:55:41,640 and then opening up that HTML document. 1112 00:55:41,640 --> 00:55:45,788 Questions about how we were able to render that HTML file? 1113 00:55:45,788 --> 00:55:52,132 AUDIENCE: Can you just give any function the index or whatever-- yeah, there. 1114 00:55:52,132 --> 00:55:53,530 BRIAN YU: As index.html? 1115 00:55:53,530 --> 00:55:54,794 AUDIENCE: No, no. 1116 00:55:54,794 --> 00:55:57,079 [INAUDIBLE] 1117 00:55:57,079 --> 00:55:58,570 BRIAN YU: Oh, good question. 1118 00:55:58,570 --> 00:56:01,080 So what is the logic behind the name of this function? 1119 00:56:01,080 --> 00:56:02,670 Does it have to be called index? 1120 00:56:02,670 --> 00:56:03,390 The answer is no. 1121 00:56:03,390 --> 00:56:05,880 Your functions can be called whatever you want. 1122 00:56:05,880 --> 00:56:07,800 But often times later on we'll see how it 1123 00:56:07,800 --> 00:56:12,395 can be helpful to refer to a particular route by the name of the function. 1124 00:56:12,395 --> 00:56:14,520 And so making sure that the names of your functions 1125 00:56:14,520 --> 00:56:17,680 are logical or meaningful in some way is usually a good idea. 1126 00:56:17,680 --> 00:56:20,204 But this could be called anything theoretically. 1127 00:56:20,204 --> 00:56:20,704 Yeah? 1128 00:56:20,704 --> 00:56:24,148 AUDIENCE: Index.html was in a subdirectory. 1129 00:56:24,148 --> 00:56:27,100 Was it searched exhaustively [INAUDIBLE]?? 1130 00:56:27,100 --> 00:56:28,440 BRIAN YU: Good question. 1131 00:56:28,440 --> 00:56:30,930 So the question is how does it find index.html? 1132 00:56:30,930 --> 00:56:32,220 Where does it know to look? 1133 00:56:32,220 --> 00:56:34,560 Flask is only going to look immediately inside 1134 00:56:34,560 --> 00:56:37,050 of a subdirectory called templates. 1135 00:56:37,050 --> 00:56:40,950 So I have to have in the same folder as application.py a directory 1136 00:56:40,950 --> 00:56:43,760 called templates, inside of which is index.html. 1137 00:56:43,760 --> 00:56:45,510 And that is the only place that flask will 1138 00:56:45,510 --> 00:56:48,570 know to look for those individual HTML files. 1139 00:56:48,570 --> 00:56:51,420 Good question. 1140 00:56:51,420 --> 00:56:54,792 So it doesn't seem like so far that we've gained a whole lot. 1141 00:56:54,792 --> 00:56:57,000 We were able to do the differences in routes in order 1142 00:56:57,000 --> 00:56:58,050 to say hello to different people. 1143 00:56:58,050 --> 00:57:00,750 And that was something that we couldn't do with just HTML. 1144 00:57:00,750 --> 00:57:04,507 But so far what we've done now is just created an HTML page 1145 00:57:04,507 --> 00:57:06,090 that we're now displaying to the user. 1146 00:57:06,090 --> 00:57:07,560 And we haven't added a whole lot. 1147 00:57:07,560 --> 00:57:13,170 So let's try and use Python to begin to add some new features to this website 1148 00:57:13,170 --> 00:57:15,310 that we didn't have before. 1149 00:57:15,310 --> 00:57:22,780 So let's take a look at variable 0. 1150 00:57:22,780 --> 00:57:26,070 So inside of variable 0, what I have here 1151 00:57:26,070 --> 00:57:27,760 is something a little bit different. 1152 00:57:27,760 --> 00:57:29,910 So first couple of lines of the same. 1153 00:57:29,910 --> 00:57:33,260 On my default route, I'm defining a variable called headline, 1154 00:57:33,260 --> 00:57:35,970 which is set equal to hello world. 1155 00:57:35,970 --> 00:57:39,450 And now on my next line, return render template-- before, I just 1156 00:57:39,450 --> 00:57:41,280 said return the index.html template. 1157 00:57:41,280 --> 00:57:44,130 That is the html content that I want the user to see. 1158 00:57:44,130 --> 00:57:45,690 But this kind of added an extra line. 1159 00:57:45,690 --> 00:57:49,020 I've said return rendered template index.html. 1160 00:57:49,020 --> 00:57:52,980 But I've also said over here, I've passed an additional argument 1161 00:57:52,980 --> 00:57:54,540 to the rendered template function. 1162 00:57:54,540 --> 00:57:57,540 I said in addition to returning index.html, 1163 00:57:57,540 --> 00:58:01,050 you should also know that I want the variable headline 1164 00:58:01,050 --> 00:58:06,810 to be defined and index.html to be whatever headline this variable is 1165 00:58:06,810 --> 00:58:08,010 equal to. 1166 00:58:08,010 --> 00:58:13,950 So effectively, I am giving this index.html knowledge of a new variable, 1167 00:58:13,950 --> 00:58:16,710 a variable called headline, which, is in this case, 1168 00:58:16,710 --> 00:58:20,020 happens to be equal to this Python variable called headline. 1169 00:58:20,020 --> 00:58:23,550 So this is the variable that will exist inside the HTML file. 1170 00:58:23,550 --> 00:58:26,070 This is the variable that exists inside the Python file. 1171 00:58:26,070 --> 00:58:28,260 And very frequently, it's conventional to give him the same name, 1172 00:58:28,260 --> 00:58:30,250 although they don't need to have the same name. 1173 00:58:30,250 --> 00:58:32,000 So what is that going to do for me? 1174 00:58:32,000 --> 00:58:34,770 What's inside of index.html? 1175 00:58:34,770 --> 00:58:36,510 Let's take a look. 1176 00:58:36,510 --> 00:58:40,350 So inside of index.html, inside of that templates directory, 1177 00:58:40,350 --> 00:58:42,290 here's what I have. 1178 00:58:42,290 --> 00:58:44,250 HTML head, a title that says my website. 1179 00:58:44,250 --> 00:58:45,960 It's the same as what we've seen before. 1180 00:58:45,960 --> 00:58:48,990 Inside the body though is where things get a little bit interesting. 1181 00:58:48,990 --> 00:58:51,180 I have an H1 tag defining a heading that will just 1182 00:58:51,180 --> 00:58:52,830 appear at the top of the page. 1183 00:58:52,830 --> 00:58:56,395 But then in this double quotation marks I have this-- 1184 00:58:56,395 --> 00:59:00,480 or double curly braces, rather, I have double curly brace, headline, 1185 00:59:00,480 --> 00:59:02,100 and then end double curly brace. 1186 00:59:02,100 --> 00:59:04,320 And this you can think of as a placeholder. 1187 00:59:04,320 --> 00:59:06,810 In this HTML template I've effectively said 1188 00:59:06,810 --> 00:59:09,570 I have a headline that I want to plug in here. 1189 00:59:09,570 --> 00:59:12,750 And whatever the value of the variable "headline" is, 1190 00:59:12,750 --> 00:59:16,140 that is what I want to substitute into this HTML template. 1191 00:59:16,140 --> 00:59:18,450 So my HTML template doesn't know in advance 1192 00:59:18,450 --> 00:59:21,540 the headline is supposed to be hello world or just hello or welcome 1193 00:59:21,540 --> 00:59:23,160 or some other heading altogether. 1194 00:59:23,160 --> 00:59:25,380 But as soon as I have a variable called headline 1195 00:59:25,380 --> 00:59:30,090 and I pass it into the index.html file, then index.html 1196 00:59:30,090 --> 00:59:34,260 will be rendered in such a way that the headline will 1197 00:59:34,260 --> 00:59:37,060 be filled in to that H1 tag. 1198 00:59:37,060 --> 00:59:41,630 So if I run flask run right now and go to that web page, 1199 00:59:41,630 --> 00:59:45,750 it says hello world, not because I had hello world inside of index.html. 1200 00:59:45,750 --> 00:59:46,710 I don't. 1201 00:59:46,710 --> 00:59:50,160 But because in my Python code, I've defined this headline hello world. 1202 00:59:50,160 --> 00:59:54,580 And that is what is getting passed into my index.html template. 1203 00:59:54,580 --> 00:59:58,260 So if I change this hello to just hello without the world 1204 00:59:58,260 --> 01:00:01,200 and refresh the page, now that headline updates as well, 1205 01:00:01,200 --> 01:00:03,660 because the timeout is being dynamically generated, 1206 01:00:03,660 --> 01:00:08,560 rendered by flask, depending upon what I pass into it as variables. 1207 01:00:08,560 --> 01:00:10,840 Headline is hello in that case. 1208 01:00:10,840 --> 01:00:13,706 Questions about how that worked? 1209 01:00:13,706 --> 01:00:14,206 Yeah? 1210 01:00:14,206 --> 01:00:17,200 AUDIENCE: Can you go back to index.html file? 1211 01:00:17,200 --> 01:00:20,194 So the double [INAUDIBLE] 1212 01:00:20,194 --> 01:00:21,691 BRIAN YU: This part? 1213 01:00:21,691 --> 01:00:22,689 AUDIENCE: Yeah. 1214 01:00:22,689 --> 01:00:29,675 So is that a proper syntax of that [INAUDIBLE] 1215 01:00:29,675 --> 01:00:30,850 BRIAN YU: Great question. 1216 01:00:30,850 --> 01:00:32,700 So what is this double curly brace index? 1217 01:00:32,700 --> 01:00:36,001 It doesn't really look like HTML and it doesn't really look like it's Python. 1218 01:00:36,001 --> 01:00:38,500 In fact, it's entirely different, what's called a templating 1219 01:00:38,500 --> 01:00:41,679 language, an entirely separate language called Jinja1, 1220 01:00:41,679 --> 01:00:42,970 which is a standalone language. 1221 01:00:42,970 --> 01:00:47,170 But it's a language that flask uses in its html templates 1222 01:00:47,170 --> 01:00:51,850 in order to make it easy to dynamically generate web pages. 1223 01:00:51,850 --> 01:00:55,420 And so we'll see a couple of examples of this Jinja2 syntax. 1224 01:00:55,420 --> 01:00:56,770 It's relatively intuitive. 1225 01:00:56,770 --> 01:00:59,410 And it follows a very similar style to Python. 1226 01:00:59,410 --> 01:01:01,990 So it has a lot in common with Python as you'll soon see. 1227 01:01:01,990 --> 01:01:04,150 But effectively, all we need to understand for now 1228 01:01:04,150 --> 01:01:06,640 is that the double curly braces are Jinja2's way 1229 01:01:06,640 --> 01:01:08,590 of saying substitute something here. 1230 01:01:08,590 --> 01:01:13,330 Put some value of a variable into the template wherever that was. 1231 01:01:13,330 --> 01:01:16,390 Great question though. 1232 01:01:16,390 --> 01:01:21,250 So what's the advantage of allowing me to just substitute 1233 01:01:21,250 --> 01:01:24,490 some variable into the template instead of just putting it 1234 01:01:24,490 --> 01:01:26,020 into the template itself? 1235 01:01:26,020 --> 01:01:29,470 Well, what I can do now is I can say app.route slash 1236 01:01:29,470 --> 01:01:34,000 bye, if I want to add a goodbye route in addition to a hello route. 1237 01:01:34,000 --> 01:01:37,810 And now I'll need to find a new function called by where the headline is instead 1238 01:01:37,810 --> 01:01:40,480 going to be goodbye. 1239 01:01:40,480 --> 01:01:42,910 And now I can take that same line, return render template 1240 01:01:42,910 --> 01:01:46,160 index.html where headline is equal to the headline, 1241 01:01:46,160 --> 01:01:49,190 but this time headline is goodbye instead. 1242 01:01:49,190 --> 01:01:51,370 So now I refresh this page-- 1243 01:01:51,370 --> 01:01:52,540 unexpected EOF. 1244 01:01:52,540 --> 01:01:57,850 Let's save the file and try again. 1245 01:01:57,850 --> 01:02:00,790 So we have the default route that just says hello. 1246 01:02:00,790 --> 01:02:05,140 But if I change the URL to be slash bye instead, then what happens 1247 01:02:05,140 --> 01:02:07,086 is I get goodbye to be displayed. 1248 01:02:07,086 --> 01:02:08,710 And that's going to be the new heading. 1249 01:02:08,710 --> 01:02:12,010 So I've used the same index.html template. 1250 01:02:12,010 --> 01:02:15,820 The only difference is I've changed what value I pass in as the headline. 1251 01:02:15,820 --> 01:02:18,850 And as a result, what appears in the template and ultimately what appear 1252 01:02:18,850 --> 01:02:21,460 appears in the html that the user sees is different, 1253 01:02:21,460 --> 01:02:24,130 depending upon what that was. 1254 01:02:24,130 --> 01:02:26,150 Questions about that so far? 1255 01:02:26,150 --> 01:02:26,650 Yeah? 1256 01:02:26,650 --> 01:02:30,649 AUDIENCE: This Python count as back end? 1257 01:02:30,649 --> 01:02:32,690 BRIAN YU: Does this Python file come as back end? 1258 01:02:32,690 --> 01:02:33,190 Yeah. 1259 01:02:33,190 --> 01:02:36,160 What I've written here is Python code for a back end web 1260 01:02:36,160 --> 01:02:41,050 server, that is listening for a request like, me typing in URL slash bye. 1261 01:02:41,050 --> 01:02:45,340 It processes that request and returns some response, in this case the HTML. 1262 01:02:45,340 --> 01:02:48,121 So yes, this back end Python code as you would term it. 1263 01:02:48,121 --> 01:02:48,620 Yeah? 1264 01:02:48,620 --> 01:02:50,161 AUDIENCE: And it updates dynamically? 1265 01:02:50,161 --> 01:02:52,960 Like you don't have to start the application [INAUDIBLE].. 1266 01:02:52,960 --> 01:02:53,960 BRIAN YU: Good question. 1267 01:02:53,960 --> 01:02:55,340 Does it update dynamically? 1268 01:02:55,340 --> 01:02:56,210 In this case, yes. 1269 01:02:56,210 --> 01:02:58,490 I have flask set to what's called debug mode. 1270 01:02:58,490 --> 01:03:01,070 And in debug mode flask will automatically update any time 1271 01:03:01,070 --> 01:03:02,910 I've made a change. 1272 01:03:02,910 --> 01:03:05,060 But if you're not in debug mode, then it typically 1273 01:03:05,060 --> 01:03:07,299 won't unless you restart the flask server. 1274 01:03:07,299 --> 01:03:09,590 So there are different configuration options for flask. 1275 01:03:09,590 --> 01:03:12,757 But there is a way to let it auto reload every time you make a change. 1276 01:03:12,757 --> 01:03:13,340 Good question. 1277 01:03:13,340 --> 01:03:16,040 1278 01:03:16,040 --> 01:03:20,240 So that is an example of it variables that we've been able to see, 1279 01:03:20,240 --> 01:03:23,150 where we're able to take values and plug them into templates. 1280 01:03:23,150 --> 01:03:24,952 But what else can we do with templates? 1281 01:03:24,952 --> 01:03:27,160 How can we make things a little bit more interesting? 1282 01:03:27,160 --> 01:03:29,111 Well, to introduce this, I thought we'd start 1283 01:03:29,111 --> 01:03:31,610 by looking at an example of an extremely simple website that 1284 01:03:31,610 --> 01:03:35,810 does exist out there on the internet that really just serves one purpose. 1285 01:03:35,810 --> 01:03:40,790 And that website is isitChristmas.com. 1286 01:03:40,790 --> 01:03:44,270 If I go to isitChristmas.com on today, which happens to not be Christmas 1287 01:03:44,270 --> 01:03:46,542 and I press Return, what I get is no. 1288 01:03:46,542 --> 01:03:47,750 That's all the web site does. 1289 01:03:47,750 --> 01:03:49,291 It just says no, it is not Christmas. 1290 01:03:49,291 --> 01:03:52,790 And presumably, on Christmas it would say yes, it is Christmas. 1291 01:03:52,790 --> 01:03:56,094 So what if we wanted to write a similar website for a different holiday, 1292 01:03:56,094 --> 01:03:57,260 say New Year's for instance? 1293 01:03:57,260 --> 01:04:01,610 And I want to write a isitnewyear's.com type website that says no if it's not 1294 01:04:01,610 --> 01:04:03,420 New Year's and yes if it is New Year's. 1295 01:04:03,420 --> 01:04:05,700 How might we go about doing that? 1296 01:04:05,700 --> 01:04:08,000 Well, we're going to need some sort of condition. 1297 01:04:08,000 --> 01:04:11,870 We want our template to display yes if it is in fact, New Year's. 1298 01:04:11,870 --> 01:04:14,780 And we want our template to display no if it's not New Year's. 1299 01:04:14,780 --> 01:04:17,840 So how might we go about doing that? 1300 01:04:17,840 --> 01:04:23,760 Let's take a look now at conditions and look at the code here. 1301 01:04:23,760 --> 01:04:27,290 So this is application.py for our is it New Year's website. 1302 01:04:27,290 --> 01:04:29,540 So what I've done up here is first import 1303 01:04:29,540 --> 01:04:31,609 a Python module called date time. 1304 01:04:31,609 --> 01:04:34,650 So Python has a bunch of different modules that serve different purposes. 1305 01:04:34,650 --> 01:04:36,625 And so depending on what you're trying to do, 1306 01:04:36,625 --> 01:04:38,750 different modules may serve your needs differently. 1307 01:04:38,750 --> 01:04:42,080 In this case, the date time module has a very easy way to get the current date. 1308 01:04:42,080 --> 01:04:43,550 And that's going to be useful to me as I try 1309 01:04:43,550 --> 01:04:45,540 and determine whether it's New Year's or not. 1310 01:04:45,540 --> 01:04:48,890 Then I import flask and render template, just like I did before. 1311 01:04:48,890 --> 01:04:50,600 I start my flask application. 1312 01:04:50,600 --> 01:04:54,176 I add my default route, which is going to call this index function. 1313 01:04:54,176 --> 01:04:55,550 And here's what's happening here. 1314 01:04:55,550 --> 01:04:58,520 I'm defining a variable called now, which 1315 01:04:58,520 --> 01:05:03,170 is set to datetime.datetime.now, which is Python's way of getting 1316 01:05:03,170 --> 01:05:04,820 the current date and time. 1317 01:05:04,820 --> 01:05:08,210 And so that's going to be stored inside of a variable called now. 1318 01:05:08,210 --> 01:05:11,210 And now I'm defining a Boolean variable called new year, 1319 01:05:11,210 --> 01:05:14,210 which is going to be true if it is New Year's and it's going to be false 1320 01:05:14,210 --> 01:05:15,590 if it's not New Year's. 1321 01:05:15,590 --> 01:05:17,960 And how do I know whether it's New Year's or not? 1322 01:05:17,960 --> 01:05:21,890 Well, if now.month, the month of the current date and time, 1323 01:05:21,890 --> 01:05:26,434 is equal to 1 and now.day is equal to 1, then it's New Year's. 1324 01:05:26,434 --> 01:05:28,850 So if both of these things are true, the month is equal to 1325 01:05:28,850 --> 01:05:32,580 and the day is equal to one, than it's January 1st, New Year's is true. 1326 01:05:32,580 --> 01:05:34,590 Otherwise, New Year's is going to be false. 1327 01:05:34,590 --> 01:05:36,506 And then finally, I'm returning this template. 1328 01:05:36,506 --> 01:05:41,240 Return render template index.html, where the value new year 1329 01:05:41,240 --> 01:05:45,320 is set equal to new year, which is just this Boolean variable that I just 1330 01:05:45,320 --> 01:05:46,710 created a moment ago. 1331 01:05:46,710 --> 01:05:49,370 So I'm defining this index.html template telling 1332 01:05:49,370 --> 01:05:51,530 flask I want to render that template. 1333 01:05:51,530 --> 01:05:54,890 And I'm giving it this Boolean information of whether 1334 01:05:54,890 --> 01:05:57,445 or not it is a new year or not. 1335 01:05:57,445 --> 01:05:59,570 And depending upon whether it's in New Year or not, 1336 01:05:59,570 --> 01:06:02,510 that's going to determine what I want the template to display. 1337 01:06:02,510 --> 01:06:05,240 And so let's look at index.html and figure out 1338 01:06:05,240 --> 01:06:09,680 how it's going to deal with this new year variable that I've defined here, 1339 01:06:09,680 --> 01:06:13,350 that I'm passing in to the template. 1340 01:06:13,350 --> 01:06:15,560 Let's look at index.html. 1341 01:06:15,560 --> 01:06:18,290 So it's a fairly simple html web page. 1342 01:06:18,290 --> 01:06:20,960 Inside the head I've got a title that just says is it New Year? 1343 01:06:20,960 --> 01:06:22,130 I've got some styling. 1344 01:06:22,130 --> 01:06:24,860 And the only styling is that I want everything to be centered. 1345 01:06:24,860 --> 01:06:26,780 And here's the body. 1346 01:06:26,780 --> 01:06:31,850 And here's what's going on in also the Jinja2 templating syntax. 1347 01:06:31,850 --> 01:06:35,330 I have this curly brace percent sign, which 1348 01:06:35,330 --> 01:06:40,610 is Jinja2's way of introducing Python like syntax for conditions 1349 01:06:40,610 --> 01:06:42,560 into the html file. 1350 01:06:42,560 --> 01:06:45,800 I want my html file to have if's and else's is in the same way that Python 1351 01:06:45,800 --> 01:06:47,030 has if's and else's. 1352 01:06:47,030 --> 01:06:51,780 And Jinja2 alongside flask lets us do that by using this similar syntax. 1353 01:06:51,780 --> 01:06:56,070 So inside a curly brace percentage sign I say if new year-- 1354 01:06:56,070 --> 01:06:58,700 in other words, if it is in fact, the new year, 1355 01:06:58,700 --> 01:07:00,980 then here's the HTML that I want to display. 1356 01:07:00,980 --> 01:07:02,550 Yes, happy new year. 1357 01:07:02,550 --> 01:07:08,580 Else, if it's not New Year's then I have this H1 that just says no, 1358 01:07:08,580 --> 01:07:09,650 it's not New Year's. 1359 01:07:09,650 --> 01:07:12,480 And then end they have to signify the end of the if statement. 1360 01:07:12,480 --> 01:07:15,080 So this looks slightly different from just regular Python, 1361 01:07:15,080 --> 01:07:16,290 but the words are the same. 1362 01:07:16,290 --> 01:07:20,450 If and else, for instance, those are the same keywords that you would use. 1363 01:07:20,450 --> 01:07:25,010 And this is Jinja2's way of saying I want to conditionally 1364 01:07:25,010 --> 01:07:28,910 use different html content depending upon the values of variables 1365 01:07:28,910 --> 01:07:30,540 that I'm passing into the template. 1366 01:07:30,540 --> 01:07:32,960 So if New Year's is true, this is the html 1367 01:07:32,960 --> 01:07:34,600 that should be rendered to the user. 1368 01:07:34,600 --> 01:07:37,970 Otherwise, this is the html that should be rendered instead. 1369 01:07:37,970 --> 01:07:41,900 And so I'm able to dynamically generate different HD, depending 1370 01:07:41,900 --> 01:07:45,300 upon the values of these variables. 1371 01:07:45,300 --> 01:07:53,160 So if I run flask run now and go ahead and go to my website, it just says no. 1372 01:07:53,160 --> 01:07:57,270 Today doesn't happen to be New Year's, so it's telling me no. 1373 01:07:57,270 --> 01:08:00,330 If, on the other hand, I wanted to simulate it and pretend that it is New 1374 01:08:00,330 --> 01:08:03,700 Year's, let me just-- after I set new year equal to the month is one 1375 01:08:03,700 --> 01:08:04,650 and the day is one-- 1376 01:08:04,650 --> 01:08:05,650 let me just override it. 1377 01:08:05,650 --> 01:08:07,060 New year is going to be true. 1378 01:08:07,060 --> 01:08:09,934 Let's just tell our web application that it is New Year's today, even 1379 01:08:09,934 --> 01:08:11,550 though it's not, and refresh the page. 1380 01:08:11,550 --> 01:08:12,790 And what happens now? 1381 01:08:12,790 --> 01:08:14,490 Then it says yes, happy new year. 1382 01:08:14,490 --> 01:08:17,250 So the HTML content is able to change depending 1383 01:08:17,250 --> 01:08:18,850 upon the values of the variables. 1384 01:08:18,850 --> 01:08:22,069 And if I look at the page source of this web page, 1385 01:08:22,069 --> 01:08:25,680 it just says body and then this H1 tag it says yes, happy new year. 1386 01:08:25,680 --> 01:08:30,720 There's no trace of that no that was inside of my index.html template 1387 01:08:30,720 --> 01:08:34,175 because the template gets processed and rendered first on the web server. 1388 01:08:34,175 --> 01:08:36,300 The server looks through the templates, figures out 1389 01:08:36,300 --> 01:08:40,020 the conditions, figures out what html code to include, what not to include, 1390 01:08:40,020 --> 01:08:43,620 what to plug in to particular spots, and then takes that result 1391 01:08:43,620 --> 01:08:45,609 and gives that result back to the user. 1392 01:08:45,609 --> 01:08:47,977 So the user never sees the original contents 1393 01:08:47,977 --> 01:08:50,310 of the template with all the different possible branches 1394 01:08:50,310 --> 01:08:54,090 and different possible options that could theoretically exist. 1395 01:08:54,090 --> 01:08:59,040 And so using that code, we were able to conditionally determine 1396 01:08:59,040 --> 01:09:02,580 what to display on the HTML page. 1397 01:09:02,580 --> 01:09:05,460 Questions about any of that we've seen so far 1398 01:09:05,460 --> 01:09:07,461 in terms of Python or Jinja or flask? 1399 01:09:07,461 --> 01:09:07,960 Yeah? 1400 01:09:07,960 --> 01:09:12,244 AUDIENCE: What's the reason why you put the ir else on the index.html and not 1401 01:09:12,244 --> 01:09:13,672 in the Python? 1402 01:09:13,672 --> 01:09:14,760 BRIAN YU: Great question. 1403 01:09:14,760 --> 01:09:18,630 So why did I put the if else inside the index.html instead 1404 01:09:18,630 --> 01:09:20,481 of inside of the Python code? 1405 01:09:20,481 --> 01:09:22,689 I certainly could have put it inside the Python code. 1406 01:09:22,689 --> 01:09:30,090 So I could have said something like, I want my text to be yes, 1407 01:09:30,090 --> 01:09:34,120 if it's New Year's, else if it's not New Year's, no for example. 1408 01:09:34,120 --> 01:09:38,069 I could have done something like this and then just passed in the text. 1409 01:09:38,069 --> 01:09:40,830 But as we start to deal with more complicated websites 1410 01:09:40,830 --> 01:09:43,890 where I might want entire sections of HTML 1411 01:09:43,890 --> 01:09:46,710 to appear depending upon the value of some variable, 1412 01:09:46,710 --> 01:09:50,530 the conditioning inside of the template will become very, very helpful. 1413 01:09:50,530 --> 01:09:52,529 You can imagine if this were a much longer thing 1414 01:09:52,529 --> 01:09:54,840 that I wanted to display if it were New Years, like if it were New Years, 1415 01:09:54,840 --> 01:09:56,889 I wanted balloons to appear on the screen. 1416 01:09:56,889 --> 01:09:58,680 I might have a lot of code that's necessary 1417 01:09:58,680 --> 01:10:00,510 in order to make those balloons appear. 1418 01:10:00,510 --> 01:10:04,630 And it would be infeasible to put all of that inside of the Python file itself. 1419 01:10:04,630 --> 01:10:08,430 And so the conditions just offer a way of changing the template such 1420 01:10:08,430 --> 01:10:11,661 that all of the template code is really inside the file. 1421 01:10:11,661 --> 01:10:14,160 And then just based on the settings of particular variables, 1422 01:10:14,160 --> 01:10:16,770 I decide how I particularly want to configure 1423 01:10:16,770 --> 01:10:19,080 that HTML file for my particular use case 1424 01:10:19,080 --> 01:10:22,270 for this particular user on a particular day. 1425 01:10:22,270 --> 01:10:22,770 Yeah? 1426 01:10:22,770 --> 01:10:26,256 AUDIENCE: [INAUDIBLE]? 1427 01:10:26,256 --> 01:10:27,400 BRIAN YU: Great question. 1428 01:10:27,400 --> 01:10:30,300 Do you need to install Jinja2 in order to make any of this work? 1429 01:10:30,300 --> 01:10:32,383 What you will need to do is you'll need to install 1430 01:10:32,383 --> 01:10:35,640 flask, which is the micro framework that we've been using in order 1431 01:10:35,640 --> 01:10:37,420 to generate these web applications. 1432 01:10:37,420 --> 01:10:40,210 And when you install flask, Jinja2 come along with it. 1433 01:10:40,210 --> 01:10:43,080 So as you install flask, Jinja2 will be first installed such 1434 01:10:43,080 --> 01:10:47,160 that you can use flask and take advantage of all Jinja2 features that 1435 01:10:47,160 --> 01:10:48,570 come along with it. 1436 01:10:48,570 --> 01:10:49,320 Good question. 1437 01:10:49,320 --> 01:10:49,819 Yeah? 1438 01:10:49,819 --> 01:10:55,442 AUDIENCE: So with flask, we don't use Javascript anymore at all? 1439 01:10:55,442 --> 01:10:56,446 BRIAN YU: Good question. 1440 01:10:56,446 --> 01:10:57,320 Do we use JavaScript? 1441 01:10:57,320 --> 01:10:58,570 We can still use JavaScript. 1442 01:10:58,570 --> 01:10:59,820 We haven't quite gotten there. 1443 01:10:59,820 --> 01:11:05,880 But it's totally fine to use JavaScript inside of the client side of the web 1444 01:11:05,880 --> 01:11:08,941 application, inside of the HTML file that the user ultimately sees. 1445 01:11:08,941 --> 01:11:10,690 And that works pretty well with flask too. 1446 01:11:10,690 --> 01:11:13,735 You can combine the two together. 1447 01:11:13,735 --> 01:11:14,235 Yeah? 1448 01:11:14,235 --> 01:11:18,211 AUDIENCE: Is it conventional to call it-- give it 1449 01:11:18,211 --> 01:11:21,690 the suffix html in this Jinja file? 1450 01:11:21,690 --> 01:11:22,337 BRIAN YU: Yes. 1451 01:11:22,337 --> 01:11:25,170 The question was, what is the convention for what to call the files? 1452 01:11:25,170 --> 01:11:27,720 Generally speaking, our template files are HTML, 1453 01:11:27,720 --> 01:11:29,590 even though they have Jinja added to them. 1454 01:11:29,590 --> 01:11:31,381 And so by convention, we'll still call them 1455 01:11:31,381 --> 01:11:35,910 HTML files, since their contents are predominately HTML. 1456 01:11:35,910 --> 01:11:38,130 Good questions. 1457 01:11:38,130 --> 01:11:41,067 So that was an example of conditions inside of Jinja. 1458 01:11:41,067 --> 01:11:43,650 But like Python, Jinja has a bunch of additional features too. 1459 01:11:43,650 --> 01:11:46,600 In addition to conditions, we also have loops, for example. 1460 01:11:46,600 --> 01:11:52,020 So how might we go about having some loops inside of our flask applications? 1461 01:11:52,020 --> 01:11:56,910 Let's take a look at an example of that. 1462 01:11:56,910 --> 01:12:00,870 So inside of application.py, I've here, in the default route, 1463 01:12:00,870 --> 01:12:04,110 just specified a bunch of names, Alice and Bob and Charlie. 1464 01:12:04,110 --> 01:12:07,890 And on line eight I'm returning rendering the template index.html, 1465 01:12:07,890 --> 01:12:12,270 passing in that whole list of names into my index.html template. 1466 01:12:12,270 --> 01:12:14,790 And presumably in my index.html template, 1467 01:12:14,790 --> 01:12:18,940 I want to display all of those names on the web page. 1468 01:12:18,940 --> 01:12:22,500 So what do I do inside of index.html? 1469 01:12:22,500 --> 01:12:27,310 Well, here's what's going on inside the body of this page. 1470 01:12:27,310 --> 01:12:30,180 I have a URL, which is in just an unordered list. 1471 01:12:30,180 --> 01:12:34,080 And now I have this curly brace percent sign syntax again. 1472 01:12:34,080 --> 01:12:35,850 We used that same syntax when we introduce 1473 01:12:35,850 --> 01:12:38,550 a if statement or a condition in Jinja. 1474 01:12:38,550 --> 01:12:43,260 We'll do the same thing when we want to add a for loop into our template. 1475 01:12:43,260 --> 01:12:45,480 And we have for name in names. 1476 01:12:45,480 --> 01:12:48,420 Same exact syntax as we would have used in Python. 1477 01:12:48,420 --> 01:12:51,290 And that means we're going to loop over that list of names. 1478 01:12:51,290 --> 01:12:54,170 And for each name, here is the code you want to add. 1479 01:12:54,170 --> 01:12:57,290 We want to add an li, a list item, where we 1480 01:12:57,290 --> 01:13:02,300 plug in using that double curly brace syntax the individual name. 1481 01:13:02,300 --> 01:13:05,150 And so I've effectively said create an unordered list. 1482 01:13:05,150 --> 01:13:08,000 And inside of that unordered list, for each one 1483 01:13:08,000 --> 01:13:13,670 of the names in my list of names, add a li tag, inside of which 1484 01:13:13,670 --> 01:13:16,370 is the actual name that I wanted. 1485 01:13:16,370 --> 01:13:22,220 So if I now run this application and press Return, what I get 1486 01:13:22,220 --> 01:13:25,250 is names big headline and then one list item 1487 01:13:25,250 --> 01:13:27,200 for each one of those individual names. 1488 01:13:27,200 --> 01:13:31,700 I didn't need to, on three separate occasions, type li tag name slash li. 1489 01:13:31,700 --> 01:13:33,532 I only needed to do that once. 1490 01:13:33,532 --> 01:13:35,990 And because I have it inside of this loop that looping over 1491 01:13:35,990 --> 01:13:38,810 this list of names, then it's going to dynamically generate 1492 01:13:38,810 --> 01:13:40,634 the list items as I need them. 1493 01:13:40,634 --> 01:13:42,550 And so if I were to add a fourth name, like, I 1494 01:13:42,550 --> 01:13:46,130 were to add David to my list of names and refresh it, 1495 01:13:46,130 --> 01:13:48,230 it adds another list item to that automatically, 1496 01:13:48,230 --> 01:13:52,400 updating HTML such that if I actually look at the page source what's happened 1497 01:13:52,400 --> 01:13:54,770 is it's created this unordered list and then it's 1498 01:13:54,770 --> 01:13:59,870 created one list item for each one of those items that was originally 1499 01:13:59,870 --> 01:14:02,390 inside of my original list. 1500 01:14:02,390 --> 01:14:05,208 Questions about loops or how that was able to work? 1501 01:14:05,208 --> 01:14:08,417 1502 01:14:08,417 --> 01:14:10,750 We'll take a look at a couple of other features of flask 1503 01:14:10,750 --> 01:14:12,666 that are ultimately going to be helpful as you 1504 01:14:12,666 --> 01:14:16,129 start to build a web applications using this type of technology. 1505 01:14:16,129 --> 01:14:17,920 One thing that might immediately be helpful 1506 01:14:17,920 --> 01:14:20,860 is figuring out how you link to different parts of your web 1507 01:14:20,860 --> 01:14:21,400 application. 1508 01:14:21,400 --> 01:14:24,700 You might have one route that links to another route and that route 1509 01:14:24,700 --> 01:14:27,100 needs to link back to the original route, for example. 1510 01:14:27,100 --> 01:14:28,940 How would you go about doing that? 1511 01:14:28,940 --> 01:14:34,120 Let's take a look at some URLs. 1512 01:14:34,120 --> 01:14:37,510 So inside of application.py I have two things going on. 1513 01:14:37,510 --> 01:14:42,100 I have a default route that just renders an index.html page up and a slash more 1514 01:14:42,100 --> 01:14:46,180 route that is going to render a more.html page presumably 1515 01:14:46,180 --> 01:14:49,870 for more information, more text, an additional page worth of information. 1516 01:14:49,870 --> 01:14:52,840 Nothing too crazy going on here, just two routes, each of which 1517 01:14:52,840 --> 01:14:55,670 renders a different HTML template. 1518 01:14:55,670 --> 01:14:57,440 Let's take a look at those HTML templates. 1519 01:14:57,440 --> 01:14:59,770 Here is index.html. 1520 01:14:59,770 --> 01:15:01,870 I have a heading that says first page. 1521 01:15:01,870 --> 01:15:03,640 I have a paragraph of text. 1522 01:15:03,640 --> 01:15:06,190 And then down here is where the interesting stuff happens. 1523 01:15:06,190 --> 01:15:10,140 Here is where I will link to the other route. 1524 01:15:10,140 --> 01:15:13,360 So I have here in a href tag which we've used before 1525 01:15:13,360 --> 01:15:15,370 in order to link to a different page. 1526 01:15:15,370 --> 01:15:18,190 But in this case, I'm using the special syntax curly 1527 01:15:18,190 --> 01:15:20,890 brace curly brace and then a special function 1528 01:15:20,890 --> 01:15:27,910 in Jinja URL for, and then the name of a Python function, in this case more. 1529 01:15:27,910 --> 01:15:30,820 And so what I've done here is said I want 1530 01:15:30,820 --> 01:15:34,930 to link to whatever the URLs for the more function, 1531 01:15:34,930 --> 01:15:37,000 in particular, this is the more function, 1532 01:15:37,000 --> 01:15:40,090 the one I've given the name more to, and I 1533 01:15:40,090 --> 01:15:45,100 want to just link to whatever route will take me to that function such 1534 01:15:45,100 --> 01:15:47,860 that later on down the road I might change that route. 1535 01:15:47,860 --> 01:15:52,237 That route's name might change such that it appears as different to the user. 1536 01:15:52,237 --> 01:15:54,820 But this code doesn't have to change, because all this code is 1537 01:15:54,820 --> 01:15:59,800 saying is figure out what the URL is for the more function and link there. 1538 01:15:59,800 --> 01:16:01,840 And I'm using the double curly braces to mean 1539 01:16:01,840 --> 01:16:06,800 substitute that URL in place in between the quotation marks here. 1540 01:16:06,800 --> 01:16:10,340 Likewise in more.html I have basically the exact same thing going on. 1541 01:16:10,340 --> 01:16:11,180 I have a heading. 1542 01:16:11,180 --> 01:16:16,010 This the second page, a paragraph worth of text, and then actual saying, 1543 01:16:16,010 --> 01:16:17,440 here's where I want to link to. 1544 01:16:17,440 --> 01:16:23,180 Go back to whatever route had the index name of the function for it. 1545 01:16:23,180 --> 01:16:29,020 And so what happens if I now run this application? 1546 01:16:29,020 --> 01:16:31,710 I have my first page that has a whole paragraph of text. 1547 01:16:31,710 --> 01:16:35,290 And when I click See More, that takes me to the second page. 1548 01:16:35,290 --> 01:16:37,660 And Go Back takes me back to the first page. 1549 01:16:37,660 --> 01:16:41,590 And so this URL for syntax can be used in Jinja or in my Python code 1550 01:16:41,590 --> 01:16:46,790 itself to just say get the URL that will take me to a particular function. 1551 01:16:46,790 --> 01:16:49,460 And so that's a helpful way of often linking to different files. 1552 01:16:49,460 --> 01:16:52,900 And one thing you may be noticing at this point in time, 1553 01:16:52,900 --> 01:16:56,740 is that there is a lot of similarity between my index.html file, 1554 01:16:56,740 --> 01:17:00,064 that first page that I showed you, and this more.html file, 1555 01:17:00,064 --> 01:17:01,480 the second page that I showed you. 1556 01:17:01,480 --> 01:17:04,660 In particular, they both have the same HTML head, 1557 01:17:04,660 --> 01:17:06,820 title as my website on both of them. 1558 01:17:06,820 --> 01:17:09,670 They both have this H1 at the beginning of the body that 1559 01:17:09,670 --> 01:17:11,590 has some title for the page. 1560 01:17:11,590 --> 01:17:13,060 They both have this paragraph. 1561 01:17:13,060 --> 01:17:17,030 And so ultimately these pages are very, very similar. 1562 01:17:17,030 --> 01:17:19,030 And what we might like to do is find a way 1563 01:17:19,030 --> 01:17:21,580 to factor out those commonalities such that I 1564 01:17:21,580 --> 01:17:26,470 don't need to copy paste my index.html page create a more.html page. 1565 01:17:26,470 --> 01:17:30,670 I can just take whatever is common to both of those pages 1566 01:17:30,670 --> 01:17:35,920 and use it as a layout, as a template to base these other pages on, and then 1567 01:17:35,920 --> 01:17:38,590 modify those new pages slightly in order to make 1568 01:17:38,590 --> 01:17:40,720 the necessary adjustments that I need. 1569 01:17:40,720 --> 01:17:42,994 That way, instead of writing the same code twice, 1570 01:17:42,994 --> 01:17:45,160 I can just write the basic template from my web site 1571 01:17:45,160 --> 01:17:47,980 once and fill in the blanks with whatever additional details 1572 01:17:47,980 --> 01:17:49,010 that I have. 1573 01:17:49,010 --> 01:17:51,400 So let's take a look at that in flask. 1574 01:17:51,400 --> 01:17:53,920 It's a feature called template inheritance. 1575 01:17:53,920 --> 01:17:59,500 So we'll go ahead and look at inheritance. 1576 01:17:59,500 --> 01:18:01,780 And application.py is identical. 1577 01:18:01,780 --> 01:18:04,400 The slash route just takes me to index.html. 1578 01:18:04,400 --> 01:18:07,330 The slash more route renders the more.html. 1579 01:18:07,330 --> 01:18:08,830 But here's what's different. 1580 01:18:08,830 --> 01:18:11,200 Inside of my templates directory I now have 1581 01:18:11,200 --> 01:18:15,610 three files, an index.html file, a more.html file, 1582 01:18:15,610 --> 01:18:18,250 but also a layout.html file. 1583 01:18:18,250 --> 01:18:22,100 And let's look at that layout.html first. 1584 01:18:22,100 --> 01:18:24,480 So what's going on inside of layout.html? 1585 01:18:24,480 --> 01:18:28,030 Well, I've defined the basic layout for one of the web pages 1586 01:18:28,030 --> 01:18:31,990 that I might want to have, either an index. html or in more.html. 1587 01:18:31,990 --> 01:18:33,340 I have my HTML header. 1588 01:18:33,340 --> 01:18:34,430 The title is my web site. 1589 01:18:34,430 --> 01:18:35,765 That's the same for both. 1590 01:18:35,765 --> 01:18:36,640 They both got a body. 1591 01:18:36,640 --> 01:18:39,040 They both got an H1 that's going to be the heading. 1592 01:18:39,040 --> 01:18:44,950 But here I've added some special syntax, block heading and then end block. 1593 01:18:44,950 --> 01:18:50,440 What I've done here is defined a variable section of my HTML template 1594 01:18:50,440 --> 01:18:54,910 saying that a block of HTML content could go here called heading. 1595 01:18:54,910 --> 01:18:59,760 And this is where that heading block should go, in between the H1 tags. 1596 01:18:59,760 --> 01:19:03,521 And then after the H1 tags I have another block called the body block. 1597 01:19:03,521 --> 01:19:05,770 And the heading and body are just names that I picked. 1598 01:19:05,770 --> 01:19:07,230 They could've been called anything. 1599 01:19:07,230 --> 01:19:10,020 But I'm saying I have whatever I call the body 1600 01:19:10,020 --> 01:19:15,730 block should be inserted right here into the body of my layout.html template. 1601 01:19:15,730 --> 01:19:20,580 So now as you can begin to imagine, my index.html file and my more.html file 1602 01:19:20,580 --> 01:19:24,300 don't need to redefine this entire structure of what the HTML web 1603 01:19:24,300 --> 01:19:25,320 page looks like. 1604 01:19:25,320 --> 01:19:28,760 All they would need to do is simply say here 1605 01:19:28,760 --> 01:19:31,620 is what belongs inside of the heading and here's what 1606 01:19:31,620 --> 01:19:33,060 belongs inside of the body. 1607 01:19:33,060 --> 01:19:36,750 And aside from that, just use this basic layout as my template 1608 01:19:36,750 --> 01:19:42,150 that going to inherit from when I define what index.html and more.html 1609 01:19:42,150 --> 01:19:44,050 ultimately look like. 1610 01:19:44,050 --> 01:19:46,810 So what does index.html look like? 1611 01:19:46,810 --> 01:19:48,030 Well, here's that code. 1612 01:19:48,030 --> 01:19:52,920 On line one up here, I've said extends layout.html. 1613 01:19:52,920 --> 01:19:56,700 In other words, index.html is going to be based on layout.html. 1614 01:19:56,700 --> 01:20:00,030 So let's just copy that HTML and use that as the template 1615 01:20:00,030 --> 01:20:01,120 that I'm going to use. 1616 01:20:01,120 --> 01:20:04,920 But I want to make a couple key changes or additions. 1617 01:20:04,920 --> 01:20:09,030 Inside of block heading this is what I want to be contained inside of heading. 1618 01:20:09,030 --> 01:20:11,540 I just want it to say first page. 1619 01:20:11,540 --> 01:20:14,490 And then end block to say that's the end of that heading section. 1620 01:20:14,490 --> 01:20:16,980 And then inside of the body block, here is 1621 01:20:16,980 --> 01:20:20,460 what belongs in the body of the website, this paragraph worth of text and then 1622 01:20:20,460 --> 01:20:23,040 this link to going onto the more page. 1623 01:20:23,040 --> 01:20:25,630 And that's what's contained inside of the body. 1624 01:20:25,630 --> 01:20:27,750 And so if you remember back in layout.html, 1625 01:20:27,750 --> 01:20:30,090 we had that space for where the heading should go 1626 01:20:30,090 --> 01:20:32,100 and that space for where the body should go. 1627 01:20:32,100 --> 01:20:33,930 And all that's going to happen now is when 1628 01:20:33,930 --> 01:20:38,580 I render index.html it's going to look to layout.html and try 1629 01:20:38,580 --> 01:20:42,255 to plug in this heading content into where that heading block was and plug 1630 01:20:42,255 --> 01:20:45,450 in this body content into where the body of that layout 1631 01:20:45,450 --> 01:20:49,800 was, and render the resulting HTML page. 1632 01:20:49,800 --> 01:20:53,890 And so likewise, inside of more.html I have the block 1633 01:20:53,890 --> 01:20:57,210 heading that defines a slightly different heading block and a slightly 1634 01:20:57,210 --> 01:20:58,800 different body block. 1635 01:20:58,800 --> 01:21:02,700 But ultimately, they are both extending that layout.html default 1636 01:21:02,700 --> 01:21:09,460 file that is where I am defining the general structure of my HTML page. 1637 01:21:09,460 --> 01:21:12,777 So if I run this web server now and refresh that, 1638 01:21:12,777 --> 01:21:13,860 it looks exactly the same. 1639 01:21:13,860 --> 01:21:16,840 First page, see more takes me to the second page. 1640 01:21:16,840 --> 01:21:19,770 But now notice that any change that I make in the layout 1641 01:21:19,770 --> 01:21:24,120 is going to then influence both index.html and more.html. 1642 01:21:24,120 --> 01:21:33,600 If I add an extra line like, welcome to my layout file, now suddenly 1643 01:21:33,600 --> 01:21:37,940 both on the first page and on the second page 1644 01:21:37,940 --> 01:21:39,810 they both have this additional welcome line. 1645 01:21:39,810 --> 01:21:44,040 Because this is information that was drawn from my layout.html template 1646 01:21:44,040 --> 01:21:48,782 from which both index.html and more.html are extended. 1647 01:21:48,782 --> 01:21:50,490 They're getting their content from layout 1648 01:21:50,490 --> 01:21:53,130 and basing themselves off of layout.html. 1649 01:21:53,130 --> 01:21:57,270 And so as a result of all of that, we're able to get this template inheritance 1650 01:21:57,270 --> 01:22:00,360 whereby I can make a change once and see the impact of that 1651 01:22:00,360 --> 01:22:03,240 all across the rest of the files that are also 1652 01:22:03,240 --> 01:22:05,520 inheriting from that same layout. 1653 01:22:05,520 --> 01:22:07,472 So in project 0 as you went about designing 1654 01:22:07,472 --> 01:22:10,680 a whole bunch of different HTML pages that were all about some central theme. 1655 01:22:10,680 --> 01:22:13,230 And you may have noticed that there was a lot of repetition where 1656 01:22:13,230 --> 01:22:15,570 you would need to copy different content from one page 1657 01:22:15,570 --> 01:22:17,820 onto a second page and a third page and a fourth page. 1658 01:22:17,820 --> 01:22:19,950 This offers a solution to that problem, whereby 1659 01:22:19,950 --> 01:22:23,190 you can define a simple layout that is both shared in common amongst all 1660 01:22:23,190 --> 01:22:25,950 of your pages, and then on each individual page, 1661 01:22:25,950 --> 01:22:29,470 just define the sections that are different from one page to another. 1662 01:22:29,470 --> 01:22:31,830 And this is often a better design for your websites. 1663 01:22:31,830 --> 01:22:34,140 And you can see how flask gives us the ability 1664 01:22:34,140 --> 01:22:36,690 to leverage this template inheritance in order 1665 01:22:36,690 --> 01:22:41,520 to create these websites that just have certain parts of each HTML page 1666 01:22:41,520 --> 01:22:44,240 that differ from one page to the next. 1667 01:22:44,240 --> 01:22:46,920 Questions about template inheritance or how 1668 01:22:46,920 --> 01:22:49,350 we were able to base HTML files off of other layouts? 1669 01:22:49,350 --> 01:22:53,370 1670 01:22:53,370 --> 01:22:56,410 Let's take a look at a couple of other things. 1671 01:22:56,410 --> 01:22:58,320 Let's take a look at forms now. 1672 01:22:58,320 --> 01:23:00,850 So if you remember back to our HTML lecture, 1673 01:23:00,850 --> 01:23:02,730 we talked about how you can go about creating 1674 01:23:02,730 --> 01:23:05,190 HTML forms just by using form tags. 1675 01:23:05,190 --> 01:23:08,190 But up until now, those forms didn't really do anything. 1676 01:23:08,190 --> 01:23:10,320 You would submit the form and nothing would happen. 1677 01:23:10,320 --> 01:23:13,500 Now that we have a back end server, a Python flask server that's 1678 01:23:13,500 --> 01:23:15,570 running and listening to requests, we can 1679 01:23:15,570 --> 01:23:19,420 begin to take the results of those forms and do something interesting with them. 1680 01:23:19,420 --> 01:23:26,850 So let's look at forms and look at application.py. 1681 01:23:26,850 --> 01:23:30,720 So first thing to notice is that our index function is just 1682 01:23:30,720 --> 01:23:34,650 going to be returning index.html, very similar to all of the rest of the web 1683 01:23:34,650 --> 01:23:35,700 pages we've done. 1684 01:23:35,700 --> 01:23:37,830 Don't worry about this second function for now. 1685 01:23:37,830 --> 01:23:40,930 But let's just look at index.html and see what it's doing. 1686 01:23:40,930 --> 01:23:45,660 So index.html is extending layout.html just like it did before. 1687 01:23:45,660 --> 01:23:47,990 Our heading is going to say first page. 1688 01:23:47,990 --> 01:23:50,070 And here's what's in the body of this web page. 1689 01:23:50,070 --> 01:23:52,950 It's going to be a form, and in particular, this form 1690 01:23:52,950 --> 01:23:54,660 is going to have an action. 1691 01:23:54,660 --> 01:23:58,560 The action is when I submit this form, who should be notified 1692 01:23:58,560 --> 01:24:00,960 or where should I be submitting this form to? 1693 01:24:00,960 --> 01:24:05,044 And in particular, it's going to be the URL for a function called hello 1694 01:24:05,044 --> 01:24:06,960 which we saw back an application.py, but we'll 1695 01:24:06,960 --> 01:24:08,850 take another look at that in a moment. 1696 01:24:08,850 --> 01:24:13,200 And we're saying the method for this request is going to be post. 1697 01:24:13,200 --> 01:24:15,660 So HTTP request, which we talked about before is 1698 01:24:15,660 --> 01:24:18,810 the process by which your browser makes a request to a web server 1699 01:24:18,810 --> 01:24:22,580 to get information, these requests can come in a number of different methods 1700 01:24:22,580 --> 01:24:26,280 where by default, if I go to google.com and press Return, 1701 01:24:26,280 --> 01:24:28,140 I am making a GET request. 1702 01:24:28,140 --> 01:24:30,970 I'm asking to get information from a web page. 1703 01:24:30,970 --> 01:24:33,680 And so the default request method is just yet. 1704 01:24:33,680 --> 01:24:36,480 And so far in all the flask applications we've been building, 1705 01:24:36,480 --> 01:24:41,160 we've been using that default GET request method for all of our routes. 1706 01:24:41,160 --> 01:24:44,070 But this time for our form when we're submitting data 1707 01:24:44,070 --> 01:24:47,640 to the server, oftentimes that will use a slightly different request method 1708 01:24:47,640 --> 01:24:49,020 called post. 1709 01:24:49,020 --> 01:24:52,170 And so here we're saying when I submit data to hello, 1710 01:24:52,170 --> 01:24:55,800 use the request method post to mean I want to submit data 1711 01:24:55,800 --> 01:24:58,950 as a form to the web server. 1712 01:24:58,950 --> 01:25:00,390 What data am I submitting? 1713 01:25:00,390 --> 01:25:04,812 Well, I have an input field whose type is text, whose name is name. 1714 01:25:04,812 --> 01:25:06,270 That name will now become relevant. 1715 01:25:06,270 --> 01:25:09,660 I've given a name to the input field, in this case it's just called name. 1716 01:25:09,660 --> 01:25:12,060 And the placeholder just says enter your name. 1717 01:25:12,060 --> 01:25:14,477 And then I've added a button that will submit this form. 1718 01:25:14,477 --> 01:25:16,560 So this is a form much like the ones we've already 1719 01:25:16,560 --> 01:25:18,643 seen before, the only difference is that now we've 1720 01:25:18,643 --> 01:25:24,030 enclosed it inside of a Jinja template instead of just a normal HTML file. 1721 01:25:24,030 --> 01:25:26,192 Now what's going on in application.py? 1722 01:25:26,192 --> 01:25:26,900 What's happening? 1723 01:25:26,900 --> 01:25:30,870 On line 9 here is my slash hello route. 1724 01:25:30,870 --> 01:25:33,510 And in particular, I'm telling this route here is 1725 01:25:33,510 --> 01:25:35,460 the request method you should accept. 1726 01:25:35,460 --> 01:25:38,850 People are going to be submitting data to this route via the post method. 1727 01:25:38,850 --> 01:25:43,417 They're going to be submitting data via post to this hello function. 1728 01:25:43,417 --> 01:25:45,000 So what should this hello function do? 1729 01:25:45,000 --> 01:25:48,660 Someone types in their name into the form, they press the Submission button. 1730 01:25:48,660 --> 01:25:50,100 This function gets called. 1731 01:25:50,100 --> 01:25:51,240 What happens? 1732 01:25:51,240 --> 01:25:56,220 Well, up here on line 1, from flask I've imported flask and render template 1733 01:25:56,220 --> 01:25:59,250 just as before, but I've also imported this thing called 1734 01:25:59,250 --> 01:26:03,900 request that is going to represent whatever request the user has 1735 01:26:03,900 --> 01:26:06,310 made to my web server. 1736 01:26:06,310 --> 01:26:10,560 And so now here on line 11 I'm defining a new variable called name. 1737 01:26:10,560 --> 01:26:13,920 And I'm saying name should be equal to what? 1738 01:26:13,920 --> 01:26:16,920 I'm going to take that request that the user made. 1739 01:26:16,920 --> 01:26:19,380 Access the form, request.form. 1740 01:26:19,380 --> 01:26:23,680 And let's get whatever part of the form was called name. 1741 01:26:23,680 --> 01:26:27,480 So if you remember back in the form itself, in the HTML code, on the input 1742 01:26:27,480 --> 01:26:32,280 I gave it a name attribute which was equal to in quotation marks "name." 1743 01:26:32,280 --> 01:26:36,570 That's what this is, the name of the input field that I'm trying to access. 1744 01:26:36,570 --> 01:26:39,647 And I'm going to access that input field and just call it name. 1745 01:26:39,647 --> 01:26:41,730 And what am I going to do with that variable name? 1746 01:26:41,730 --> 01:26:43,860 Well, I'm going to render a template called 1747 01:26:43,860 --> 01:26:49,440 hello.html, passing in that name as a variable into the template. 1748 01:26:49,440 --> 01:26:52,200 Just like we were passing names into the template before in order 1749 01:26:52,200 --> 01:26:55,620 to say hello to different people, this is going to do much the same thing. 1750 01:26:55,620 --> 01:26:57,520 But instead of getting the name from the URL, 1751 01:26:57,520 --> 01:27:02,130 we're going to get the name from the form that the user just filled out. 1752 01:27:02,130 --> 01:27:03,580 So how is that going to work? 1753 01:27:03,580 --> 01:27:06,440 Let's look at hello.html. 1754 01:27:06,440 --> 01:27:11,040 Inside of hello.html the heading is just going to be the word hello. 1755 01:27:11,040 --> 01:27:14,760 And the body of the website is hello, and then in those double curly 1756 01:27:14,760 --> 01:27:16,680 braces to mean plug in a value here. 1757 01:27:16,680 --> 01:27:18,840 I'm plugging in the value name, because I 1758 01:27:18,840 --> 01:27:22,410 want to say hello to whoever the name is, but I don't yet know who it is. 1759 01:27:22,410 --> 01:27:26,340 And again, both of these files are extending that basic layout.html file 1760 01:27:26,340 --> 01:27:29,980 that defines the general structure for a web page. 1761 01:27:29,980 --> 01:27:33,780 So what happens if I now run this web application? 1762 01:27:33,780 --> 01:27:34,980 I go to the web page. 1763 01:27:34,980 --> 01:27:36,110 This is the first page. 1764 01:27:36,110 --> 01:27:36,900 Here is the form. 1765 01:27:36,900 --> 01:27:38,890 I can enter my name here. 1766 01:27:38,890 --> 01:27:41,400 So if I type my name and press Submit, I'm 1767 01:27:41,400 --> 01:27:45,390 now submitting that form to the slash hello route via post. 1768 01:27:45,390 --> 01:27:48,510 I'm sending the data within the form, in this case my name, 1769 01:27:48,510 --> 01:27:50,070 to the slash hello route. 1770 01:27:50,070 --> 01:27:54,450 And what that's going to do is run the code inside of my hello function. 1771 01:27:54,450 --> 01:27:59,190 And the result of that is that it's going to say hello Brian. 1772 01:27:59,190 --> 01:28:00,780 Again, why did that happen? 1773 01:28:00,780 --> 01:28:05,550 It's because in index.html, the action, where the form should be submitted to, 1774 01:28:05,550 --> 01:28:07,890 is the hello function. 1775 01:28:07,890 --> 01:28:11,550 Then inside of application.py, here is the hello function. 1776 01:28:11,550 --> 01:28:12,930 What happens inside of it? 1777 01:28:12,930 --> 01:28:18,130 I first get the name from the form, request.form.getname. 1778 01:28:18,130 --> 01:28:20,220 Save it in a variable called name. 1779 01:28:20,220 --> 01:28:23,940 And then render the template hello.html, passing that name variable 1780 01:28:23,940 --> 01:28:28,175 in as a value that I want to then display in the resulting template. 1781 01:28:28,175 --> 01:28:30,426 And so now I've created a form just like I did before, 1782 01:28:30,426 --> 01:28:32,008 but I'm doing something with the form. 1783 01:28:32,008 --> 01:28:34,560 I'm taking the data that the user passed into the form, 1784 01:28:34,560 --> 01:28:38,760 and using it to generate a dynamic HTML page just for them. 1785 01:28:38,760 --> 01:28:42,020 Questions about forms or how we made that happen? 1786 01:28:42,020 --> 01:28:42,710 Yeah? 1787 01:28:42,710 --> 01:28:45,650 AUDIENCE: What happens if you just typed in the URL dash hello? 1788 01:28:45,650 --> 01:28:46,740 BRIAN YU: Great question. 1789 01:28:46,740 --> 01:28:49,240 Question is what happens if, instead of submitting the form, 1790 01:28:49,240 --> 01:28:50,340 which goes to slash hello? 1791 01:28:50,340 --> 01:28:56,550 I were to instead, just go to this URL slash hello, and just 1792 01:28:56,550 --> 01:28:57,720 press Return there? 1793 01:28:57,720 --> 01:29:01,080 So recall that when you type in a URL and just press Return, 1794 01:29:01,080 --> 01:29:03,300 that is a get request. 1795 01:29:03,300 --> 01:29:05,310 The default request method in HTTP is just 1796 01:29:05,310 --> 01:29:07,539 trying to get the contents of a web page. 1797 01:29:07,539 --> 01:29:10,080 And here, I'm just going to ask to get the contents of hello. 1798 01:29:10,080 --> 01:29:13,140 I'm not submitting any form data to hello. 1799 01:29:13,140 --> 01:29:15,090 What I get is method not allowed. 1800 01:29:15,090 --> 01:29:18,570 This method is not allowed for the requested URL. 1801 01:29:18,570 --> 01:29:19,950 And why is that the case? 1802 01:29:19,950 --> 01:29:23,610 What is it about these four lines that caused 1803 01:29:23,610 --> 01:29:27,040 me to get a method not allowed error? 1804 01:29:27,040 --> 01:29:29,580 Any guesses? 1805 01:29:29,580 --> 01:29:32,820 Yeah, it's this method equals post part of the route that 1806 01:29:32,820 --> 01:29:37,590 says the only request methods I should accept is the request method post. 1807 01:29:37,590 --> 01:29:39,939 If someone just tries to get the page normally, 1808 01:29:39,939 --> 01:29:43,230 then there should be some sort of error, because that's not a supported request 1809 01:29:43,230 --> 01:29:44,280 method. 1810 01:29:44,280 --> 01:29:45,849 I could try to support both. 1811 01:29:45,849 --> 01:29:48,390 I could say I want to support both, just someone typing flash 1812 01:29:48,390 --> 01:29:53,280 hello, and someone going to the regular route and submitting the form via post. 1813 01:29:53,280 --> 01:29:56,880 And to do that, I would just say method equals GET and POST. 1814 01:29:56,880 --> 01:29:59,550 I can have a list of different requests methods that I allow. 1815 01:29:59,550 --> 01:30:03,570 And here I'm saying the flash slow route will accept both GET requests and POST 1816 01:30:03,570 --> 01:30:04,620 requests. 1817 01:30:04,620 --> 01:30:06,090 How do I tell them apart? 1818 01:30:06,090 --> 01:30:09,060 Well, I can use this request object again. 1819 01:30:09,060 --> 01:30:17,130 I can say if request.method equals GET, for instance, let's just return 1820 01:30:17,130 --> 01:30:25,020 please submit the form instead, else, if the request method isn't GET, 1821 01:30:25,020 --> 01:30:29,400 which means the request method has to be POST, then do the same thing as before. 1822 01:30:29,400 --> 01:30:32,700 Get the name, and then return the hello.html template 1823 01:30:32,700 --> 01:30:34,600 with the name filled in. 1824 01:30:34,600 --> 01:30:39,030 Now if I go to slash hello, what I get is please submit the form instead. 1825 01:30:39,030 --> 01:30:42,180 Because I tried to access this page via GET. 1826 01:30:42,180 --> 01:30:45,660 But instead, if I just go to the default page and type in my name, 1827 01:30:45,660 --> 01:30:48,750 and submit that form, then I get the hello. 1828 01:30:48,750 --> 01:30:52,260 So flask is able to detect what the request method is. 1829 01:30:52,260 --> 01:30:56,370 And if the request method is GET, do one thing, if the request method is POST, 1830 01:30:56,370 --> 01:30:57,530 do something else. 1831 01:30:57,530 --> 01:30:59,610 And so flask can differentiate between just 1832 01:30:59,610 --> 01:31:04,950 trying to access the page versus trying to actually submit data to that page. 1833 01:31:04,950 --> 01:31:07,050 Other questions about that or other things? 1834 01:31:07,050 --> 01:31:10,220 1835 01:31:10,220 --> 01:31:12,080 We'll take a look at one other example. 1836 01:31:12,080 --> 01:31:16,520 So, so far, our web applications haven't been able to-- 1837 01:31:16,520 --> 01:31:17,920 question? 1838 01:31:17,920 --> 01:31:18,616 Yeah? 1839 01:31:18,616 --> 01:31:24,448 AUDIENCE: So if the form had a GET method specified with [INAUDIBLE],, 1840 01:31:24,448 --> 01:31:27,364 would the request form get-- 1841 01:31:27,364 --> 01:31:31,660 BRIAN YU: So the question is if the form, instead of being method POST, 1842 01:31:31,660 --> 01:31:36,260 were method GET, and I tried to submit by the GET method instead? 1843 01:31:36,260 --> 01:31:40,070 Well, in this case, it's going to get caught in request.method equals GET. 1844 01:31:40,070 --> 01:31:42,950 So what will happen is that if I go to the default route 1845 01:31:42,950 --> 01:31:45,770 and try to type in my name and submit it, I'm going to get 1846 01:31:45,770 --> 01:31:48,440 please submit the form instead, because it was a GET request. 1847 01:31:48,440 --> 01:31:53,180 But hypothetically, you could also have data submitted via GET instead. 1848 01:31:53,180 --> 01:31:57,020 When you submit data via GET, that data gets put into the URL. 1849 01:31:57,020 --> 01:32:01,760 So notice that what changed here is that I requested slash hello 1850 01:32:01,760 --> 01:32:05,240 and then question mark name equals Brian, where that basically 1851 01:32:05,240 --> 01:32:08,240 means that I've submitted form data via GET, 1852 01:32:08,240 --> 01:32:10,840 and that data is all put into the URL. 1853 01:32:10,840 --> 01:32:13,610 And so the result of that is that you can 1854 01:32:13,610 --> 01:32:17,090 change what's in the URL to change what the specific request is. 1855 01:32:17,090 --> 01:32:19,850 This is also not a good idea if there's any sensitive information 1856 01:32:19,850 --> 01:32:21,308 that you want to submit via a form. 1857 01:32:21,308 --> 01:32:24,779 If someone's typing in their password for example, to log in to your website, 1858 01:32:24,779 --> 01:32:27,320 you don't want that form to be submitted via GET, because now 1859 01:32:27,320 --> 01:32:30,530 in the URL, that appears in their URL history for example. 1860 01:32:30,530 --> 01:32:33,330 Their password's just going to be plainly visible in the text. 1861 01:32:33,330 --> 01:32:35,990 And so oftentimes, for more secure form submissions 1862 01:32:35,990 --> 01:32:39,200 you'll want to use POST requests instead of GET. 1863 01:32:39,200 --> 01:32:41,120 But you could also submit data via GET too. 1864 01:32:41,120 --> 01:32:43,680 1865 01:32:43,680 --> 01:32:46,760 I'm just going to change that back to POST. 1866 01:32:46,760 --> 01:32:48,960 Good question, though. 1867 01:32:48,960 --> 01:32:50,960 So thus far, our web applications haven't really 1868 01:32:50,960 --> 01:32:53,330 been able to store information. 1869 01:32:53,330 --> 01:32:56,300 We've been able to use web applications in order 1870 01:32:56,300 --> 01:32:59,030 to take information and do something with it, 1871 01:32:59,030 --> 01:33:00,920 whether it was the name that someone typed 1872 01:33:00,920 --> 01:33:02,575 into the URL to say hello to them. 1873 01:33:02,575 --> 01:33:04,700 Or whether it was a form that users are filling out 1874 01:33:04,700 --> 01:33:07,325 that they fill out the form, press Submit, and then the website 1875 01:33:07,325 --> 01:33:08,240 says hello to them. 1876 01:33:08,240 --> 01:33:10,730 But now we'd like to create a website that 1877 01:33:10,730 --> 01:33:13,970 is able to store information, retain information, and use 1878 01:33:13,970 --> 01:33:16,680 that information later, for example. 1879 01:33:16,680 --> 01:33:20,520 And that's where we can start to introduce the concept of sessions. 1880 01:33:20,520 --> 01:33:23,180 And so sessions in flask or in web programming, more 1881 01:33:23,180 --> 01:33:27,890 generally is the idea that when you log in to the web site, 1882 01:33:27,890 --> 01:33:35,420 you have access to some session that is data specific to your user account. 1883 01:33:35,420 --> 01:33:38,450 So I log into Google.com. 1884 01:33:38,450 --> 01:33:41,000 And I see that I'm logged into my Google account 1885 01:33:41,000 --> 01:33:43,490 and have access to my Google documents, for instance. 1886 01:33:43,490 --> 01:33:46,970 Whereas you might log into Google and see an entirely different thing, 1887 01:33:46,970 --> 01:33:50,190 depending upon how you are logged in as well. 1888 01:33:50,190 --> 01:33:54,410 So how can we begin to make use of those sessions? 1889 01:33:54,410 --> 01:33:57,290 Let's take a look at a example. 1890 01:33:57,290 --> 01:34:03,640 1891 01:34:03,640 --> 01:34:07,430 So this doesn't yet actually use sessions. 1892 01:34:07,430 --> 01:34:09,740 But it's an example of us being able to store data. 1893 01:34:09,740 --> 01:34:13,790 So let's say I wanted to create a note taking application, for example. 1894 01:34:13,790 --> 01:34:15,940 So how might I create a note taking application 1895 01:34:15,940 --> 01:34:19,780 where I want to be able to store different types of notes 1896 01:34:19,780 --> 01:34:22,930 that people are typing in order to record notes and save notes 1897 01:34:22,930 --> 01:34:24,010 on this website? 1898 01:34:24,010 --> 01:34:25,670 So what do I have going on? 1899 01:34:25,670 --> 01:34:29,400 On line 10 I've defined this notes variable 1900 01:34:29,400 --> 01:34:32,380 to so far, just be an empty list. 1901 01:34:32,380 --> 01:34:34,420 It's just going to be an empty list of notes 1902 01:34:34,420 --> 01:34:37,720 that is going to store the notes that I'm eventually going to be saving. 1903 01:34:37,720 --> 01:34:43,030 Then I have a default index route, where inside of this index route, 1904 01:34:43,030 --> 01:34:44,950 I have a couple of things going on. 1905 01:34:44,950 --> 01:34:47,770 If the request method is POST, which we haven't yet seen. 1906 01:34:47,770 --> 01:34:50,307 But if I were to submit data to the index form-- and I'm 1907 01:34:50,307 --> 01:34:51,890 not sure how I would do that just yet. 1908 01:34:51,890 --> 01:34:53,020 But we'll see in a moment. 1909 01:34:53,020 --> 01:34:54,550 Then what do I want to do? 1910 01:34:54,550 --> 01:34:58,330 I want to access whatever note I wanted to add presumably, 1911 01:34:58,330 --> 01:35:00,160 because I just tried to add a note. 1912 01:35:00,160 --> 01:35:05,830 And then notes.append note it's my way of saying take this list of notes 1913 01:35:05,830 --> 01:35:07,270 and add a new thing to the list. 1914 01:35:07,270 --> 01:35:11,032 In particular, add this new note to that list. 1915 01:35:11,032 --> 01:35:13,240 So that's what happens if the request method is POST. 1916 01:35:13,240 --> 01:35:17,380 If I submit data to this index function, then what I should do 1917 01:35:17,380 --> 01:35:19,900 is add a new note to my list of notes. 1918 01:35:19,900 --> 01:35:24,670 And then otherwise, if I didn't submit any data, or even if I did, 1919 01:35:24,670 --> 01:35:31,570 just at the end, return this index.html passing in my list of notes. 1920 01:35:31,570 --> 01:35:34,010 What's happening inside of index.html? 1921 01:35:34,010 --> 01:35:41,830 Well, what I have here is a for note in note, print out each individual note. 1922 01:35:41,830 --> 01:35:45,220 And all of that is stored inside of an unordered list 1923 01:35:45,220 --> 01:35:47,090 where have an ordered list of notes. 1924 01:35:47,090 --> 01:35:50,530 So what that's going to do, is much like we saw that list of names 1925 01:35:50,530 --> 01:35:53,500 that we could then use to generate one name at a time 1926 01:35:53,500 --> 01:35:55,360 in order to display a list of names, we can 1927 01:35:55,360 --> 01:35:58,570 display a list of notes that will display one note at a time 1928 01:35:58,570 --> 01:36:01,390 on each item inside an unordered list. 1929 01:36:01,390 --> 01:36:04,270 Then lower down on the page, I have a form. 1930 01:36:04,270 --> 01:36:07,120 And this form is presumably where I could add a new note 1931 01:36:07,120 --> 01:36:09,370 into my notepad web application. 1932 01:36:09,370 --> 01:36:13,150 This form is going to have an action of going to the index page, that's 1933 01:36:13,150 --> 01:36:14,440 where I want it to go. 1934 01:36:14,440 --> 01:36:16,239 The method is POST, just like before. 1935 01:36:16,239 --> 01:36:18,280 And this is very similar to the form we just saw. 1936 01:36:18,280 --> 01:36:22,130 It's got an input field whose name is note this time, and whose 1937 01:36:22,130 --> 01:36:24,850 place holder is enter your note here, and then a button 1938 01:36:24,850 --> 01:36:28,447 to add a note to my list of notes. 1939 01:36:28,447 --> 01:36:30,530 So we'll take a look at all that in just a moment. 1940 01:36:30,530 --> 01:36:32,740 But let's take a look at how the web application actually works. 1941 01:36:32,740 --> 01:36:34,656 And then take a closer look at what's actually 1942 01:36:34,656 --> 01:36:37,570 going on inside of flask and the application.py 1943 01:36:37,570 --> 01:36:39,220 to make all of that possible. 1944 01:36:39,220 --> 01:36:41,870 So I'll go ahead and flask run this. 1945 01:36:41,870 --> 01:36:45,040 I'll go to the default route. 1946 01:36:45,040 --> 01:36:48,240 And what I see here is just a heading that says notes and then this form. 1947 01:36:48,240 --> 01:36:50,290 Enter note here, and then add note. 1948 01:36:50,290 --> 01:36:54,490 So what happens if I type hello as a note and click Add Note? 1949 01:36:54,490 --> 01:36:57,190 Well, that will add hello as just a note that I've now 1950 01:36:57,190 --> 01:36:58,510 recorded inside of this list. 1951 01:36:58,510 --> 01:37:01,590 And if I add hello again, as another note? 1952 01:37:01,590 --> 01:37:03,370 It adds that too. 1953 01:37:03,370 --> 01:37:04,780 So how is that working? 1954 01:37:04,780 --> 01:37:07,630 Let's take another look back at index.html. 1955 01:37:07,630 --> 01:37:09,430 When I add a note, what's happening? 1956 01:37:09,430 --> 01:37:10,930 I'm submitting this form. 1957 01:37:10,930 --> 01:37:14,090 And I'm submitting this form back to the index function 1958 01:37:14,090 --> 01:37:17,200 or whatever URL maps to the index function, which in this case is just 1959 01:37:17,200 --> 01:37:18,040 slash. 1960 01:37:18,040 --> 01:37:20,710 And I'm submitting that data via POST. 1961 01:37:20,710 --> 01:37:23,230 What's then happening inside of application.py? 1962 01:37:23,230 --> 01:37:26,089 Well, I'm maintaining this list of notes right here, 1963 01:37:26,089 --> 01:37:27,880 just an empty list to start out with, which 1964 01:37:27,880 --> 01:37:29,860 is why I have no notes to begin with. 1965 01:37:29,860 --> 01:37:33,310 But then in the index function, if the request method was POST, 1966 01:37:33,310 --> 01:37:36,910 if I did try and add a note, then what's going to happen? 1967 01:37:36,910 --> 01:37:40,420 I'm going to set note equal to whatever is 1968 01:37:40,420 --> 01:37:43,600 the note parameter of that form, whatever thing in the form 1969 01:37:43,600 --> 01:37:45,430 had a name called note. 1970 01:37:45,430 --> 01:37:49,240 And then I'm going to append to my already existing list of notes, 1971 01:37:49,240 --> 01:37:50,440 that new note. 1972 01:37:50,440 --> 01:37:52,540 And then only at the end of all of that am 1973 01:37:52,540 --> 01:37:55,330 I going to render the template index.html, 1974 01:37:55,330 --> 01:37:57,570 passing in that whole list of notes. 1975 01:37:57,570 --> 01:37:59,680 And what that's going to do is ultimately save 1976 01:37:59,680 --> 01:38:04,240 all of those notes as a variable that is accessible to my entire web 1977 01:38:04,240 --> 01:38:05,450 application. 1978 01:38:05,450 --> 01:38:13,330 And so what's going to happen then is that if I type in a third note 1979 01:38:13,330 --> 01:38:16,550 and add the note, that's going to appear. 1980 01:38:16,550 --> 01:38:20,440 And if, for example, I were to close this web page, but open it up later 1981 01:38:20,440 --> 01:38:23,090 and type in the URL again, those notes are still there. 1982 01:38:23,090 --> 01:38:26,110 My web server is saving the value of all those notes 1983 01:38:26,110 --> 01:38:29,230 as a variable inside of the web server. 1984 01:38:29,230 --> 01:38:32,230 And as a result, I can see all those notes even if I close the web page 1985 01:38:32,230 --> 01:38:33,355 and open it up again later. 1986 01:38:33,355 --> 01:38:34,870 Those notes are still retained. 1987 01:38:34,870 --> 01:38:38,720 If on the other hand, I were to ever for some reason shut down my web server. 1988 01:38:38,720 --> 01:38:42,460 And you can quit flask by pressing Control-C, for example, 1989 01:38:42,460 --> 01:38:45,251 and start up again by typing flask run, now 1990 01:38:45,251 --> 01:38:46,750 I've restarted the whole web server. 1991 01:38:46,750 --> 01:38:49,420 It's completely restarted application.py. 1992 01:38:49,420 --> 01:38:53,000 And when I refresh this page, now my notes are gone again. 1993 01:38:53,000 --> 01:38:57,307 And so I've lost access to all of them because the server was shut down. 1994 01:38:57,307 --> 01:38:59,140 And when it restarted, everything was reset. 1995 01:38:59,140 --> 01:39:01,473 And so next week we'll begin to look at database design, 1996 01:39:01,473 --> 01:39:04,950 and how we can resolve this problem by trying to figure out 1997 01:39:04,950 --> 01:39:08,450 how do we take data that the user submitted and store it somewhere longer 1998 01:39:08,450 --> 01:39:10,760 term, somewhere that even if the server goes down 1999 01:39:10,760 --> 01:39:13,730 and come back later or even if we're accessing it from somewhere else, 2000 01:39:13,730 --> 01:39:15,660 we can still get back at that same data. 2001 01:39:15,660 --> 01:39:18,560 And so that's where using and taking advantage of databases 2002 01:39:18,560 --> 01:39:20,450 will become quite helpful. 2003 01:39:20,450 --> 01:39:23,870 But one last thing to note about this particular website 2004 01:39:23,870 --> 01:39:26,960 is that this notes variable is what we call 2005 01:39:26,960 --> 01:39:30,090 a global variable, accessible across the entire application, 2006 01:39:30,090 --> 01:39:34,100 which means that if I'm using this web application and taking notes with it, 2007 01:39:34,100 --> 01:39:37,280 and potentially, someone else also wants to use my web 2008 01:39:37,280 --> 01:39:39,260 application on the internet, presumably, we 2009 01:39:39,260 --> 01:39:42,975 don't want to be working with the same note pad, so to speak. 2010 01:39:42,975 --> 01:39:46,100 I want to be able to take my own notes without seeing someone else's notes. 2011 01:39:46,100 --> 01:39:48,890 And I don't want someone else to be able to see my notes. 2012 01:39:48,890 --> 01:39:51,050 But if I just have the single notes variable that's 2013 01:39:51,050 --> 01:39:53,390 shared across the entire web server, then 2014 01:39:53,390 --> 01:39:56,030 even if someone else tries to visit my website, 2015 01:39:56,030 --> 01:39:59,750 they're going to see all of that entire same set of notes. 2016 01:39:59,750 --> 01:40:02,420 And so that's where the concept of sessions 2017 01:40:02,420 --> 01:40:05,420 begins to come in, that when I log into my web site, 2018 01:40:05,420 --> 01:40:07,160 I want to see my list of notes. 2019 01:40:07,160 --> 01:40:10,190 And when someone else logs into the same web site, 2020 01:40:10,190 --> 01:40:13,370 they want to see their list of notes without those lists of notes 2021 01:40:13,370 --> 01:40:15,194 ever overlapping, so to speak. 2022 01:40:15,194 --> 01:40:16,610 And so how do we make that happen? 2023 01:40:16,610 --> 01:40:19,440 What changes do we need to make in order to allow for that? 2024 01:40:19,440 --> 01:40:23,870 Well, what we're going to do is from flask, import session. 2025 01:40:23,870 --> 01:40:28,820 And that gives us access to a variable called session, which we can then 2026 01:40:28,820 --> 01:40:33,860 use them in order to keep variables and values that are specific 2027 01:40:33,860 --> 01:40:37,070 to a particular user, such that I have my own session that's 2028 01:40:37,070 --> 01:40:39,710 all data specific to my interactions with the website, 2029 01:40:39,710 --> 01:40:42,920 and someone else has their own session that has all of the data specific 2030 01:40:42,920 --> 01:40:45,170 to their interactions with their website. 2031 01:40:45,170 --> 01:40:49,190 And then on line two I'm importing a special additional extension 2032 01:40:49,190 --> 01:40:50,900 to flask called flask session. 2033 01:40:50,900 --> 01:40:54,890 This just give us a little bit more control over sessions, in particular, 2034 01:40:54,890 --> 01:40:58,490 it lets us store session "server side" such that on our server 2035 01:40:58,490 --> 01:41:00,860 we're storing all the data about the sessions which 2036 01:41:00,860 --> 01:41:03,890 gives us just a little more control over how the sessions are managed. 2037 01:41:03,890 --> 01:41:05,990 But not to worry too much about that. 2038 01:41:05,990 --> 01:41:09,050 What's important is that I now have access to this variable called 2039 01:41:09,050 --> 01:41:16,600 session which is unique to me, such that now if I, instead of saying that notes 2040 01:41:16,600 --> 01:41:20,000 is going to be this global variable that everyone has access to, 2041 01:41:20,000 --> 01:41:23,990 I can treat the session as a dictionary that is specific to me. 2042 01:41:23,990 --> 01:41:33,170 So I can say session square bracket notes is equal to the empty list, 2043 01:41:33,170 --> 01:41:37,620 to mean I want my particular session to have an empty list of notes, 2044 01:41:37,620 --> 01:41:39,350 for example. 2045 01:41:39,350 --> 01:41:46,850 And then, instead of notes.appendnote, I can say sessionnotes.append notes. 2046 01:41:46,850 --> 01:41:51,200 Rather than append this new note to the entire global variable representing 2047 01:41:51,200 --> 01:41:54,080 all of the notes, I only want to append the note 2048 01:41:54,080 --> 01:41:56,840 to the notes specific to my particular session, 2049 01:41:56,840 --> 01:41:59,510 to my interaction with this page. 2050 01:41:59,510 --> 01:42:02,780 So what's going to happen here now if I try and run 2051 01:42:02,780 --> 01:42:09,578 this web application is I can try and type my first note and nothing happens. 2052 01:42:09,578 --> 01:42:13,322 AUDIENCE: You missed the last line, [INAUDIBLE] 2053 01:42:13,322 --> 01:42:14,570 BRIAN YU: Oh, wonderful. 2054 01:42:14,570 --> 01:42:15,710 Thank you. 2055 01:42:15,710 --> 01:42:18,840 So notes should be session notes instead. 2056 01:42:18,840 --> 01:42:21,560 And if I run this again, it say notes. 2057 01:42:21,560 --> 01:42:22,856 I type in my first note. 2058 01:42:22,856 --> 01:42:23,480 I add the note. 2059 01:42:23,480 --> 01:42:24,760 Now the first note appears. 2060 01:42:24,760 --> 01:42:26,551 What happens if I try adding a second note? 2061 01:42:26,551 --> 01:42:30,680 What's going to happen? 2062 01:42:30,680 --> 01:42:31,940 It overwrote the first note. 2063 01:42:31,940 --> 01:42:33,960 First note went away. 2064 01:42:33,960 --> 01:42:34,820 Why did that happen? 2065 01:42:34,820 --> 01:42:35,819 Any ideas? 2066 01:42:35,819 --> 01:42:38,110 AUDIENCE: You're resetting the session notes each time. 2067 01:42:38,110 --> 01:42:39,050 BRIAN YU: Exactly. 2068 01:42:39,050 --> 01:42:41,690 On line 14 here, I've reset session notes. 2069 01:42:41,690 --> 01:42:45,080 So I needed to give session notes some initial value in order 2070 01:42:45,080 --> 01:42:48,410 to say if session notes doesn't exist, it needs to have something. 2071 01:42:48,410 --> 01:42:50,690 But if I have it here in the index function, then 2072 01:42:50,690 --> 01:42:53,220 every single time I submit new data to index, 2073 01:42:53,220 --> 01:42:55,220 it's going to clear out all of my own old notes. 2074 01:42:55,220 --> 01:42:56,900 And that's clearly not what I want. 2075 01:42:56,900 --> 01:43:01,615 So maybe I want something like this, if session.getnotesisnone. 2076 01:43:01,615 --> 01:43:05,330 2077 01:43:05,330 --> 01:43:07,830 In other words, if I try and get the notes from the session 2078 01:43:07,830 --> 01:43:13,680 and it doesn't exist, then I want session notes to be an empty list. 2079 01:43:13,680 --> 01:43:16,250 In other words, if I didn't have any notes already, 2080 01:43:16,250 --> 01:43:18,230 let's initialize notes to be an empty list. 2081 01:43:18,230 --> 01:43:19,790 That way it exists, at least. 2082 01:43:19,790 --> 01:43:22,980 But otherwise, let's just keep it as what it is. 2083 01:43:22,980 --> 01:43:24,650 So now it's a second note. 2084 01:43:24,650 --> 01:43:28,490 Now if I type third note and add a note, it adds the third note 2085 01:43:28,490 --> 01:43:30,270 just like we would expect it to. 2086 01:43:30,270 --> 01:43:34,730 And so the advantage here is that now I have multiple different sessions going 2087 01:43:34,730 --> 01:43:39,440 on, such that this particular user is independent of other particular users. 2088 01:43:39,440 --> 01:43:42,720 We don't have one shared notes variable across all of the different users. 2089 01:43:42,720 --> 01:43:44,390 And if you were to eventually go to my website 2090 01:43:44,390 --> 01:43:47,270 if I hosted somewhere on the internet, that will have its own set of notes, 2091 01:43:47,270 --> 01:43:49,730 and so on and so forth, so that everyone's user accounts 2092 01:43:49,730 --> 01:43:51,140 can be kept separate. 2093 01:43:51,140 --> 01:43:55,550 And so questions about sessions, or how we might go about storing data inside 2094 01:43:55,550 --> 01:43:56,660 of our flask applications? 2095 01:43:56,660 --> 01:43:59,726 AUDIENCE: So if you close the browser now, you lose your notes? 2096 01:43:59,726 --> 01:44:03,030 BRIAN YU: If I close the browser now and then go back to it, 2097 01:44:03,030 --> 01:44:04,020 I get to keep my notes. 2098 01:44:04,020 --> 01:44:06,020 Because it's still stored inside of the session. 2099 01:44:06,020 --> 01:44:06,820 AUDIENCE: It knows your session? 2100 01:44:06,820 --> 01:44:08,320 BRIAN YU: It knows my session, yeah. 2101 01:44:08,320 --> 01:44:10,910 2102 01:44:10,910 --> 01:44:14,480 It is able to identify my particular web browser 2103 01:44:14,480 --> 01:44:18,620 request by a cookie, just a value that's being stored inside the web browser. 2104 01:44:18,620 --> 01:44:21,440 And so the next time that I make another request to that web page, 2105 01:44:21,440 --> 01:44:24,180 it recognizes me and says oh, I know exactly who you are. 2106 01:44:24,180 --> 01:44:26,540 Here are the notes that I have saved for you. 2107 01:44:26,540 --> 01:44:29,282 And it can display my notes back to me that way as well. 2108 01:44:29,282 --> 01:44:31,490 And so you can imagine this being useful for websites 2109 01:44:31,490 --> 01:44:33,781 where you have to log in and see particular data that's 2110 01:44:33,781 --> 01:44:34,780 very pertinent to you. 2111 01:44:34,780 --> 01:44:34,920 Yeah? 2112 01:44:34,920 --> 01:44:38,056 AUDIENCE: Just to be clear, so line 10 in your file is no longer needed. 2113 01:44:38,056 --> 01:44:40,250 BRIAN YU: Line 10 in this file is no longer needed 2114 01:44:40,250 --> 01:44:43,400 because I no longer have a global notes that is shared across everyone. 2115 01:44:43,400 --> 01:44:47,810 I only have notes that are very specific to a particular user's session. 2116 01:44:47,810 --> 01:44:48,410 Good question. 2117 01:44:48,410 --> 01:44:51,330 2118 01:44:51,330 --> 01:44:51,830 Yes? 2119 01:44:51,830 --> 01:44:55,566 AUDIENCE: Is there any website that describes all of this kind 2120 01:44:55,566 --> 01:44:56,732 of [INAUDIBLE]? 2121 01:44:56,732 --> 01:44:58,940 BRIAN YU: Is there a website that describes all this? 2122 01:44:58,940 --> 01:44:59,440 Yeah. 2123 01:44:59,440 --> 01:45:01,070 So flask has great documentation. 2124 01:45:01,070 --> 01:45:02,820 If you just go to flask's web site, you'll 2125 01:45:02,820 --> 01:45:05,030 see descriptions of basically all of these features 2126 01:45:05,030 --> 01:45:09,380 plus more in great detail, giving you examples of different features of using 2127 01:45:09,380 --> 01:45:10,590 the flask framework. 2128 01:45:10,590 --> 01:45:13,790 So what we've seen so far is just a taste of what flask is able to do. 2129 01:45:13,790 --> 01:45:17,810 We've seen it able to build routes for us, build templates for us. 2130 01:45:17,810 --> 01:45:21,500 We've been able to add logic like loops and conditions into flask templates 2131 01:45:21,500 --> 01:45:22,070 as well. 2132 01:45:22,070 --> 01:45:24,028 But it's got a whole lot more features as well. 2133 01:45:24,028 --> 01:45:27,560 And in particular, next week we'll be diving into building databases 2134 01:45:27,560 --> 01:45:30,100 and connecting databases to flask, such that flask 2135 01:45:30,100 --> 01:45:32,780 can better interact with data that's provided by users, such 2136 01:45:32,780 --> 01:45:35,660 that we can better manage user accounts and manage relationships 2137 01:45:35,660 --> 01:45:37,180 across different kinds of data. 2138 01:45:37,180 --> 01:45:39,460 And all of that is coming next week. 2139 01:45:39,460 --> 01:45:41,054 But for now, that's Python and flask. 2140 01:45:41,054 --> 01:45:42,470 And we'll conclude here for today. 2141 01:45:42,470 --> 01:45:44,320 Thank you all. 2142 01:45:44,320 --> 01:45:46,593