Placeholder Image

字幕列表 影片播放

  • [MUSIC PLAYING]

  • DAVID MALAN: All right, this is CS50, and this is lecture 9.

  • And so we've been diving into bunches of languages

  • recently among them have been HTML, and CSS, and Python most recently.

  • And soon we're going to see JavaScript soon.

  • We're going to see SQL and more.

  • So let's see just a moment if we can kind of wrap our minds around what's

  • going on with these various languages.

  • So HTML, which we looked at a couple of weeks back, is used for what?

  • AUDIENCE: Websites.

  • DAVID MALAN: Websites.

  • OK, but be more specific.

  • What about websites?

  • AUDIENCE: Markup.

  • DAVID MALAN: Markup.

  • OK, be more specific than markup.

  • What does that mean?

  • AUDIENCE: The way they look.

  • DAVID MALAN: The way they look.

  • OK, good, so marking up a website, the structure of the website,

  • and the contents of the website are what you would annotate using HTML--

  • Hypertext Markup Language.

  • It's not a programming language, so it doesn't

  • have functions, and loops, and conditions,

  • and the kind of logical control that we've used for some time.

  • It really is about presenting information.

  • Make something bold.

  • Make something italics.

  • Put something centered and so forth.

  • CSS, meanwhile, allows you to really take things the final mile

  • and really get the aesthetics just right.

  • And so, in fact, what I just described, boldfacing, and italics, and centering,

  • early on in version 1 say of HTML was actually how you did it.

  • There was no CSS.

  • But these days, the better approach is to factor out those kinds of aesthetics

  • from your HTML and instead put them in this other language, CSS, Cascading

  • Style Sheets.

  • So your HTML now becomes put this text in a column.

  • Put this other text in another column.

  • And structure your data in a certain way.

  • And then stylize it with colors, and fonts, and placement using CSS.

  • Now meanwhile, most recently, we introduced Python.

  • And what was noteworthy about Python?

  • What do you got?

  • Some-- back here?

  • Python--

  • AUDIENCE: More straightforward syntax.

  • DAVID MALAN: More straightforward syntax, yeah, in some ways,

  • and we'll see some syntax where you take that back, I think.

  • But in general, that is kind of the case,

  • because you don't need parentheses if they're not strictly necessary.

  • You don't need curly braces just because.

  • Instead, things like indentation become more important, which on the one hand

  • is a little annoying, but on the other hand,

  • really does reinforce good habits.

  • So that's probably a good thing.

  • And then at the very end of the last lecture,

  • we did something that was hopefully wonderfully inspiring,

  • which was to implement what in Python?

  • AUDIENCE: Dictionary?

  • DAVID MALAN: The dictionary.

  • And so we've really, we pretty much re-implemented

  • all of problem set 5 speller using like I don't know, 15, 20, 25 lines of code,

  • not to mention I was able to type it out within 30 seconds.

  • And that's not just because I knew what I wanted to type,

  • but really because you have to write so few lines of code.

  • With Python, and soon with JavaScript, and even other languages out there,

  • you just get so much more functionality for free.

  • If you want to know the length of the string, you call a function.

  • If you want to get a linked list, you create a data structure called a List.

  • If you want a hash table, you create a data structure called a Dictionary.

  • You don't implement it yourself.

  • Underneath the hood, someone else out there in the world

  • has implemented all of that functionality for us.

  • But now we're standing on their shoulders.

  • And so today, what we begin to do is to transition

  • to this last portion of the class, where our domain is not just a command line

  • and dot slash something, but web programming, where the ideas are pretty

  • much going to be the same so long as we now understand, as hopefully you

  • do or are beginning to, what HTTP is and how the web and the internet

  • itself work.

  • So recall that we looked a little bit ago at a URL like this.

  • And so if you were to visit https://www.facebook.com and hit

  • Enter in your browser, you're going to send some kind of message

  • in an envelope that might physically in our world look like this.

  • But of course, it's digital instead.

  • And what is inside of that envelope, if you simply

  • do type that URL before trying to get to Facebook?

  • AUDIENCE: An error message that redirects to--

  • I guess [INAUDIBLE] that one.

  • DAVID MALAN: Yeah, probably no error message here, because that URL

  • did have the HTTPS.

  • And it wouldn't so much be an error message,

  • but like a preference to go to a different location.

  • AUDIENCE: Moved?

  • DAVID MALAN: Sorry?

  • AUDIENCE: Moved.

  • Moved, like permanently moved.

  • DAVID MALAN: Oh moved.

  • Not moved, only if we had gone to a shorter URL.

  • Recall that all of those 301 one redirects

  • were the result of, for instance, leaving off the dub dub dub

  • or leaving off the S. so this is actually the good.

  • This was the end of the story, where everything just worked and we got back

  • a 200 OK.

  • So if I did hit Enter though on my laptop and tried to visit that URL,

  • what did I put, or my laptop put inside of this envelope?

  • AUDIENCE: Request.

  • DAVID MALAN: The request to get an address, so it was like the get verb,

  • like getme, probably slash, because the last thing in this URL is the slash.

  • It probably had a Host header.

  • Recall, we saw host colon and then the domain name of the website again.

  • And there were bunches of other headers, so to speak,

  • that we kind of turned a blind eye to.

  • But in essence, atop the piece of paper, virtually,

  • that's inside of this envelope, or at least these two lines, a reminder

  • as well as to what protocol, sort of what handshake convention,

  • we are trying to use with the server.

  • And now when the server responds with an envelope of its own,

  • how do these headers change?

  • What's inside of Facebook's HTTP headers in its envelope back to me?

  • Kind of spoiled it a moment ago.

  • What?

  • AUDIENCE: The IP address?

  • DAVID MALAN: Somewhere-- let's kind of consider that

  • on the outside of the envelope, though.

  • That's how it gets to me.

  • What's on the inside?

  • What's the status code going to be when I visit Facebook's Home page?

  • AUDIENCE: 200 OK

  • DAVID MALAN: 200 OK-- and so we saw 200 OK only when we actually

  • looked underneath the hood, so to speak, to see

  • what was inside of these envelopes using Chrome's Inspector

  • toolbar, the developer tools, or using cURL, that command line program.

  • Odds are, there are other headers in there,

  • like content type is text slash html.

  • And I think that's the only one we saw.

  • But moving forward, as you make your own web-based applications,

  • you will actually see and Chrome and other tools a whole bunch

  • of different content types.

  • You'll see like image slash ping or image slash jpeg.

  • So indeed, anytime you download a picture

  • of a cat or something from the internet, included

  • in the headers in that envelope are two lines like this.

  • But a cat is not a web page.

  • It's not HTML.

  • So this would be like image slash jpeg, if it's a photograph of a cat.

  • And then below that though, the dot dot dot,

  • is where things started to get interesting in the last half

  • of our lecture on HTTP, because what came below all of the HTTP headers

  • inside of this envelope from Facebook?

  • What's inside of the envelope?

  • AUDIENCE: Nothing?

  • DAVID MALAN: Nothing-- yes, it's technically an answer.

  • But--

  • AUDIENCE: Isn't it like pieces of the file?

  • DAVID MALAN: Yeah, it's the pieces in the file.

  • I mean, it really is the file itself.

  • So essentially, when you write a letter in the human world,

  • you usually put like the date.

  • And you might put the person's address.

  • And you might put like dear so-and-so.

  • You can kind of think of all of that like metadata,

  • the stuff that's not really the crux of your message to the human,

  • as being the HTTP headers.

  • But then once you start writing your first paragraph

  • and the actual substantive part of your letter, that's going to be down here,

  • so to speak.

  • And that's going to be the HTML inside of this envelope.

  • So if I'm downloading Facebook's Home page via my browser to my computer,

  • and I am seeing Facebook's Home page or my news feed, or if I'm logged in,

  • all of that HTML is actually inside of this envelope.

  • Now technically, it's all zeros and ones at the end of the day.

  • But now that we're not sort of at week zero anymore,

  • we're thinking in terms of language, there's just a whole bunch of HTML.

  • And what did that HTML look like?

  • Well in the simplest case, it might have looked like this.

  • This is a simpler web page certainly than Facebook's own.

  • But this would be an example of the first paragraph,

  • so to speak, of Facebook's Home page coming from server to browser.

  • And so that's the relationship among HTTP and HTML and, in turn,

  • CSS, though there's none pictured here.

  • HTTP is that protocol, that set of conventions,

  • ala the human handshake that ensures that the data is formatted

  • in a certain way and gets to me from server

  • to browser, or from browser to server.

  • Below that is a very specific language called

  • HTML, which is the actual content.

  • And what does my browser do upon receiving this?

  • Well, just like we humans would read the first paragraph of the letter,

  • a browser is going to read this top to bottom, left to right,

  • and do what it says.

  • Hey, browser, here is a web page.

  • Hey, browser, here is the head of the page.

  • Hey, browser, here is the title.

  • Put it in the tab bar.

  • Hey, browser, here's the body.

  • Put it in the big rectangular region of the window.

  • Hey, browser, that's it for the web page.

  • So you can think of these open tags and close tags or start tags and end

  • tags as really being these directives.

  • Do something; stop doing something.

  • And that's literally what the browser is doing underneath the hood.

  • So the last time we introduced Python, which is unrelated fundamentally

  • to all of this.

  • It is just another programming language.

  • So technically we could have started talking about Python in like week 1,

  • right after we looked at Scratch instead of looking at C.

  • But instead, we started sort of with Scratch, the graphical program.

  • Then we kind of went super low level with C,

  • and built, and built, and built on top of it,

  • until now we're kind of at Python, where we can solve all of those same problems

  • with Python.

  • And in fact, one of the challenges of problem

  • set 6 is going to be to rewind a few weeks and re-implement Mario,

  • and Cash or Credit, or Caesar, or Vigenere in Python,

  • so that you effectively have your own solutions handy, or the staff

  • solutions in C. And it'll be really kind of a warm-up

  • exercise and a comforting exercise to just translate something

  • that you know works or should work to a new language

  • and see the mapping from one to another, just like we did with Speller,

  • but more powerfully.

  • We're also going to start to build applications using Python

  • that we've not built before.

  • And so among them, for instance, today will

  • be a handful of examples that actually use Python

  • to generate HTML from a server to me.

  • Because you could write this on your Mac or PC.

  • You could save it.

  • You could upload it to a server in the cloud, so to speak.

  • And people can visit it.

  • But if I visit this page today, or tomorrow, or the next day,

  • it's always going to be the same.

  • It's going to say hello title, hello body every day.

  • Facebook, and Gmail, and any website out there these days is much more dynamic.

  • The content changes based on you or other humans,

  • typically, or even the time of day, if it's a new site.

  • So today we're going to explore, how do you use programming,

  • in Python in particular, to generate dynamic content,

  • ultimately based on data in your database interactions

  • from the user or any number of other things.

  • So how do we go about doing this?

  • Well, let me go ahead and open up the IDE for just a moment

  • and open up an example from today's source code called serve.py.

  • This is an example, a few of whose features might look a little familiar,

  • but not all of them.

  • So let me scroll to the bottom first.

  • This is a program written in Python that implements a web server.

  • So remember, a server--

  • even though most of us, at least I certainly grew up thinking of it

  • as a physical machine--

  • it's technically a piece of software running on a physical machine.

  • So just to be clear, what does a web server do?

  • What's its purpose in life?

  • AUDIENCE: Like connects to the internet.

  • DAVID MALAN: Connects-- a little too grand--

  • its functionality is actually much more narrowly defined, I would say.

  • What's a web server?

  • That's kind of like a router interconnects things.

  • AUDIENCE: Door?

  • DAVID MALAN: What's that?

  • AUDIENCE: Your door to the internet.

  • DAVID MALAN: Door to the-- even too fancy

  • a description-- let's really home in on what it does functionally.

  • AUDIENCE: It listens for requests and then responds to them?

  • DAVID MALAN: Right, so a much less interesting answer,

  • but much more concrete and factual as to what the server does.

  • Exactly, it is a piece of software that just listens for HTTP requests

  • on the internet coming in what? --via wired or wireless connections.

  • As soon as it hears an HTTP request, like get slash,

  • it responds to those requests.

  • So that is what the web server does.

  • So Facebook.com, and Google.com, and all of these companies

  • have web server software running on physical machines that

  • are just constantly listening for those requests.

  • And the photo I showed last time of that old rack at Google's headquarters

  • is an example of a whole bunch of servers

  • that were running the same software, all of which

  • had internet connections that were just listening for HTTP connections,

  • specifically, if we want to get really precise from a few weeks

  • back, on TCP port 80, on a certain IP address.

  • But again, we can kind of abstract away from that.

  • And as you say, it's listening for connections on the internet.

  • So how does this piece of software work?

  • Just to demonstrate how relatively easy it

  • is to write a web server, irrespective of the content it serves up, line 24,

  • if you could translate it into English for me,

  • based only on last week's material, what is line 24 doing?

  • And it's not configure server.

  • More technically, what does line 24 do in Python?

  • AUDIENCE: It's just assigning port the number 8080.

  • DAVID MALAN: To?

  • Oh, yes, OK, to port.

  • So, OK, so what is port exactly?

  • AUDIENCE: Just a variable.

  • DAVID MALAN: Just a variable-- what is its data type?

  • AUDIENCE: It's an int.

  • DAVID MALAN: How do you know that?

  • I don't see int.

  • AUDIENCE: Or the input is given as an int.

  • And Python just dynamically figures is out somehow.

  • AUDIENCE: Exactly, so we-- unlike C, you don't specify the types anymore,

  • but they do exist--

  • ints, and strings, and floats, and so forth.

  • But honestly, why do we really need to specify int

  • if it's obvious to the human, let alone should be to the computer,

  • that the thing on the right is an int.

  • Just make the thing on the left an int.

  • And this is one of the features you get of Python, and in general, more

  • modern languages.

  • Meanwhile, line 25 is similar in spirit.

  • Give me a variable called server address.

  • But this we didn't talk about too much last time.

  • I mentioned the word only in passing.

  • This is a little funky.

  • We never saw this syntax in C in this context--

  • parenthesis something comma something close parenthesis.

  • We absolutely saw that syntax when we were calling functions and so forth,

  • or when we had if conditions or the like, or loops, and while loops,

  • and for loops.

  • But we've never seen, to my recollection, a pair of parentheses

  • open and close that have nothing next to them

  • other than, in this case, the equal sign.

  • But what does this kind of look like maybe from other classes you've taken?

  • [INTERPOSING VOICES]

  • DAVID MALAN: Yeah, sorry, say again.

  • You want to go with ordered pair?

  • Yeah, so if you think to any math class or graphing class,

  • anytime you dealt with x and y, it's kind of common in certain worlds

  • to have pairs of numbers, or triples of numbers, or quads of numbers.

  • And so Python actually supports that idea.

  • If you have two related values that you want to kind of cluster

  • together in your mind, you can simply do open parenthesis one value comma

  • the other.

  • And the general term for this is a tuple--

  • T-U-P-L-E. So it's kind of like a double or a triple.

  • But a tuple is any number of things, one or more things in parentheses.

  • So why are these related?

  • Well, in TCP/IP, the protocol spoken on the internet,

  • the first thing is the IP address.

  • The second thing is the TCP port.

  • So we have both IP and TCP, ergo, TCP/IP.

  • And so we're just storing both of those variables in this--

  • both of those values in this address called server address.

  • Meanwhile, this kind of code we wouldn't really be familiar with yet.

  • But this is declaring another variable on the left called httpd,

  • d meaning daemon, which is a synonym for server, so HTTP server, aka web server.

  • Give me some kind of HTTP server object.

  • This is like a special struct, like a student struct.

  • But this struct actually implements a web server,

  • passing in the server address and whatever this thing here is.

  • And let me wave my hand at that for just a moment.

  • But then the last line of code here on 29, says inside of that variable

  • is a function, otherwise known as a method,

  • called serve forever that literally does that.

  • When you run this program, and it gets to line 29,

  • the program never, ever ends.

  • It doesn't exit.

  • It just keeps staying there.

  • Never again do you see a prompt.

  • It literally is serving forever by listening for HTTP requests.

  • Now let me just show you what this does now.

  • Let me go ahead in my terminal window.

  • And how do I run a Python program?

  • AUDIENCE: Python [INAUDIBLE].

  • DAVID MALAN: Exactly-- so it's this.

  • Unlike C, you literally say Python, which is not only

  • the name of the language but it's the name

  • of the program, the interpreter that can understand this file.

  • And if I go ahead and run that, I can't open file serve.py.

  • Up No such file in directory.

  • So technically, I didn't mean to do that.

  • But teachable moment, what's going wrong?

  • AUDIENCE: You're not in the right folder.

  • DAVID MALAN: Yeah, I'm not in the right folder.

  • So before I mentioned it's in Today's Source Code, Source 9, so let

  • me just cd into the right directory, and now do it again.

  • And now nothing seems to be happening forever.

  • And so it seems like the server is actually running.

  • So I'm actually going to go ahead and do this.

  • Let me go ahead and go up to Web Server under the Menu here.

  • I just have a little warning from Cloud9.

  • I'm going go ahead and click App.

  • And now notice what's happening.

  • My new URL is going to look different than your URL might.

  • But in my case here, I just went to ide50 dash malan dash Harvard dot edu--

  • because that's my username on Cloud9--

  • dot cs50 dot io colon 8080.

  • Because this program, this server, it is listening for TCP connections

  • on port 8080, not the default, but 1880.

  • And as soon as it hears a connection, it literally

  • spits out apparently "hello, world."

  • So where is that coming from?

  • Well, if I zoom out and go back to my program here and look at the top,

  • we'll see what this thing actually is.

  • And we won't have to get into the particulars of why this works.

  • But this is how a web server functions at the end of the day.

  • When a web server receives an envelope from a user's browser, like this one

  • here, it looks inside and it realizes, oh, this is a GET request.

  • Because literally the verb GET is inside of the envelope.

  • So here is a function called doget, just because.

  • And then what do we do?

  • This line here, 13, is telling the server to send 200, OK.

  • It's telling it to send this header, content type text HTML.

  • And it's telling it to write the following string, "hello, world,"

  • in what's called Unicode or UTF-8 out on the internet.

  • And that's it.

  • So this is a very specific example.

  • This web server is not all that useful, because no matter who or how often you

  • connect to this web server on port 8080 of your domain

  • name, what is it going to show?

  • AUDIENCE: Hello, world.

  • DAVID MALAN: Hello, world--

  • so not interesting-- you might as well have

  • just save the whole darn thing as like index.html and be done with it,

  • and not use Python at all.

  • But what if, what if instead of doing this, you have code in your web server

  • that says something like this--

  • figure out what file was requested from HTTP headers,

  • because remember it might be slash.

  • It might be slash zuck, for Mark Zuckerberg's Home page,

  • or some other request.

  • Check if that file exists.

  • If so, send it back to browser.

  • In other words, suppose we remove this hard-coded stuff about "hello, world,"

  • and just start to write some code, or at least for now

  • pseudocode, that makes the web server dynamic.

  • Upon getting a request on port 8080, it checks what the request is for,

  • per this first line 12.

  • If it finds it on the hard drive locally,

  • it's going to send it back to the user.

  • And so ultimately, that is what a web server does.

  • I hard-coded a simple one to just forever say,

  • "hello, world." but that's what a web server does.

  • And moving forward, we are not going to implement the web server itself

  • in Python.

  • We're instead going to use a tool, a pretty popular one called Flask.

  • So there's bunches and bunches of different web server software

  • out there in the world.

  • Flask happens to be one of them.

  • It's technically called a micro framework,

  • because it's like a small amount of code that other people wrote just

  • to make it easier to serve up websites.

  • And so rather than write the web server ourselves,

  • we're going to use a web server that someone else wrote, Flask,

  • and actually start writing our own applications on the web with it.

  • So now what does this mean?

  • Let me go ahead and do the following back here in the IDE.

  • Let me ahead and kill this server here, close that file here,

  • and let me go ahead and let's say do this.

  • I'm going to go ahead and create a new file.

  • And if I Google this, Python--

  • Python Flask, the only way I would know what I'm about to do

  • is if I had looked up the documentation for Flask

  • and I followed the instructions, literally read the documentation.

  • And at one point, I kind of read through the user guide here.

  • I looked at some examples.

  • I played around with my IDE, saved some things and tried them out.

  • And thus was born this kind of example.

  • So if you want to use Flask, it turns out you essentially have to do this.

  • You first define an application.

  • And you say, Flask name.

  • Why?

  • Why?

  • It's not all that useful for now for us to dive into the weeds here.

  • But this just says, hey, Flask, give me a web app.

  • I don't care how it's implemented.

  • You take care of that, so I don't have to write code

  • like the previous serve.py file.

  • And then after that, I need to tell flask what to do and when.

  • And so the way you do this in a lot of modern web software

  • is you define what are called routes.

  • You say to Flask, or your web server more generally,

  • hey, server, if you get a request for slash, do this.

  • If you get a request for slash zuck, do this.

  • If you get a slash for slash login, do this other thing.

  • And so the pseudocode in a server might be something like this--

  • if request is for slash, then send back home page.

  • Else if request is for slash zuck, which again was just one of the sample URLs

  • two times ago, then send Mark's Home page.

  • Else if the request is for login, then prompt user to log in, and so forth.

  • So this is a web-based application, albeit in pseudocode.

  • It has nothing to do with TCP/IP per se.

  • That is going to be the job of the web server to deal with.

  • I don't want to even know there are envelopes virtually on the internet.

  • I just want to start writing code in my logic.

  • Just like in C, I want to write my main function and my helper functions.

  • Here is what my web application is going to do.

  • So how do you do this?

  • Well, suppose that you want to do the following.

  • Let me go into--

  • save this as application.py, which is just a convention, application.py.

  • And let me create momentarily another file called index.html.

  • So I need a really quick web page here.

  • And this will come with practice, but let me go ahead

  • and just quickly whip up a little web page-- head here,

  • title, hello, title, and then down here body, and hello body.

  • OK, so super simple web page, same as we did a couple of weeks back.

  • That's all.

  • It's in a file called index.html.

  • How do I now connect these two files?

  • If I have a program written in Python, or technically pseudocode,

  • and one of the things I want this program to do is this pseudocode here--

  • if request is for slash, then send back the Home page.

  • We've branch into, I think, briefly a couple times ago

  • that the default Home page for a website is often, just

  • by human convention, called index.html.

  • So this pseudocode now is kind of this.

  • If the request is for slash, specifically send back index.html.

  • But instead, if the request is for slash zuck, then send Mark's Home page.

  • So what might that look like?

  • Let me actually go and copy this, make a new file.

  • And just for kicks, I'm going to save it as a zuck.html and then hello, world,

  • I am Mark.

  • So suppose this is Mark's Profile page.

  • It's super simple.

  • It's obviously not what Facebook looks like.

  • But it is a valid HTML page.

  • So now I have two files and one web application.

  • So technically, I should really send back zuck.html.

  • And if I continue this sort of imaginary example, then prompt user to log in,

  • that probably means then show user login.html,

  • which is yet another page that has like a form on it.

  • It's just like the form we made for our simple Google example.

  • So in short, all a web application is, it's

  • a program written in some language that respond

  • to requests based on some logic.

  • And this is the logic that we did not have in HTML alone.

  • This is why we need Python, or Java, or Ruby, or PHP,

  • or any number of other languages can do the same thing.

  • C can also do this, but it would be an awful, awful nightmare

  • to implement this in C. Because just think of how annoying

  • it is to like compare substrings or extract something like the HTTP headers

  • from a longer-- it's just a lot of work.

  • A fun fact-- two years ago we had problem set, where we did exactly

  • that, but now it's a little different.

  • So here's how we transition to making this an actual web app.

  • Let me go ahead and translate this to actual code.

  • Let me delete this.

  • And it turns out, in Flask, if you want to find a route, so to speak,

  • for slash, you do this.

  • My app shall have a route for slash.

  • And when that route is visited by a user,

  • by making a request in one of these envelopes,

  • go ahead and call a function in Python called index--

  • though I could call it anything I want--

  • that simply returns the result of rendering a template called index.html.

  • And we'll see why that is called a template in just a bit.

  • But know that Flask gives me this special function called Render

  • Template that will spit out a file.

  • But it does more than that, which is why it has a fancier name.

  • The file I want it to spit out is index.html.

  • Meanwhile, if I want to support Mark Zuckerberg's Home page,

  • I'm going to do what then, if you just kind of infer?

  • AUDIENCE: Def zuck.

  • DAVID MALAN: Def, OK, zuck.

  • AUDIENCE: And then return his-- the rendered template.

  • DAVID MALAN: Yeah, so return render template of zuck.html.

  • And one more thing--

  • AUDIENCE: [INAUDIBLE] backslash zuck.

  • DAVID MALAN: Backslash-- backslash where?

  • No need for backslash or escape characters,

  • but there's one-- one of these things is not like the other at the moment.

  • AUDIENCE: [INAUDIBLE].

  • DAVID MALAN: Yeah, so we need to define this function as being,

  • quite simply, the function that Flask should call when the user visits

  • slash zuck.

  • Now again, it seems a little stupid that we've written zuck

  • in three places, index in two places.

  • That's just kind of the way it is in Flask.

  • Like this could just be Foo.

  • This could be bar.

  • The function names don't matter.

  • But you might as well keep yourself sane and use the same names

  • as relate to the routes themselves.

  • So now we've replaced two of my conditions in my pseudocode

  • with actual code.

  • And if we take this one step further, to do the Login screen.

  • I bet I just need to do something like app dot route slash login and then

  • maybe something like def login return render template login dot html, which

  • I didn't bother making, but I certainly could

  • with some copy/paste and some edits.

  • So now we have a web application that supports three routes.

  • When it gets a request in an envelope from someone on the internet,

  • it will look inside that envelope and check, what are you requesting?

  • Well, if you're requesting slash, I'm going to this function.

  • If you're requesting slash zuck, I'm going to call this function.

  • Or slash login, I'm going to call that function.

  • And that's it.

  • The web app is not complete because notice,

  • we seem to have no code that actually checks usernames, and passwords,

  • and sort of fancy features that you would hope actually exist.

  • But that's more code to come.

  • For now, all we're doing is spitting out, conditionally, different files.

  • So how do I now make this work?

  • Well turns out, I need to make a directory called templates,

  • so make dir templates-- or I could do it with the file browser, with the GUI--

  • Enter.

  • I'm going to move both index.html in there with mv.

  • And I'm going to move mark into there with mv.

  • And now I need to do one other thing.

  • In my program up here, I've deliberately-- whoops,

  • oh, let's close the tabs, because I moved the files.

  • That's OK.

  • It's just because I moved the files into a subdirectory.

  • So let me re-open those.

  • So I left the room appear deliberately for a couple of reasons.

  • One, Flask-- rather Python--

  • has no idea what Flask is.

  • When Python was invented years ago, there was no such thing as Flask.

  • That was written more recently by a community

  • of people, who have been making better web server software since.

  • So if I want to use a package that someone else wrote, aka a library,

  • recall that I can do something like this from Flask import FLASK, which

  • is a little stupid looking.

  • But this just means somewhere on the IDE,

  • we have pre-installed a package called Flask.

  • Inside of there is a feature called FLASK-- capital letters--

  • which happens to be what I'm using here.

  • And for today's purposes, you can think of this as a structure.

  • It's not a student struct, which is the go to example thus far.

  • But it's a special web app structure that I'm somehow using.

  • But you can just take on faith for now that that's what that does.

  • But render template is also not a function that I implemented.

  • And indeed, nowhere in the file is it actually defined or implemented.

  • Turns out that comes with Flask, so I can also import a second function.

  • Just like I imported get int or get string or get float,

  • I can import this function called render template.

  • And that's all I actually need here.

  • So now I'm going to go ahead, and if I didn't make any typos,

  • I'm going to go ahead and now do this--

  • Flask run.

  • So Flask, in addition to being like a framework, a way of writing

  • web applications, it is also a little program

  • called Flask that takes some command line arguments, one of which

  • is Run, which just says run the web app in my current directory.

  • And that file, by convention, has to be called application.py.

  • So when I hit Enter, I see a whole bunch of debugging output.

  • Debugger is active.

  • We'll see what that means some time.

  • And now here is the URL.

  • It's really ugly looking, because I have a pretty long user name here on Cloud9,

  • but notice it's the port 8080 that's important.

  • Let me go ahead and open that.

  • And now I see "hello, body."

  • But up here-- and remember that the slash is inferred.

  • Chrome is just being used friendly and hiding it.

  • If I change this to zuck--

  • Enter-- "I am Mark."

  • And if I change it to login, what's going to happen?

  • AUDIENCE: Nothing, because it--

  • DAVID MALAN: Not found-- so something deliberately at this time it's going

  • to go wrong because I didn't--

  • whoa-- OK, so I didn't bother making that template yet.

  • And so you'll soon be familiar, not with segfaults any more,

  • but probably with something called an exception.

  • And we'll see more of these over time.

  • But Python, unlike C, supports something called exceptions, which

  • is a type of error that can happen.

  • And essentially, one of the features, if a little cryptic, of Flask,

  • is that anytime something really goes wrong like a segfault, but in this case

  • called an exception, you'll see a somewhat pretty web page

  • that I did not write.

  • I didn't make any of this HTML.

  • Flask generates that for me just to show me

  • all of the darn errors that somehow ensued,

  • so I can try to wrap my mind around what's going on.

  • Fortunately, the most important one is usually at the top.

  • And it kind of says what I need to know-- "template not found,"

  • even though I'm not sure what this means yet, "login.html."

  • So I can infer from that what's actually gone wrong.

  • So that might be my very first example.

  • And the key takeaways here are that I have written Python code with logic

  • to decide, if the request comes in for this, do this.

  • If the request comes in for some other thing, do this,

  • else do this other thing, so kind of a three-way fork in the road,

  • even though the results are just some text files.

  • OK, any questions or confusions at this point?

  • OK, so now that we have a programming language,

  • we can do much more powerful things, kind

  • of sort of like I tried to do back in my day

  • when I first learned how to write web applications.

  • And one of the first things I did--

  • let me go ahead and close all of this up.

  • One of the first things I did was to make a website for the Freshmen

  • Intramural Sports Program.

  • And let me go ahead in here to Frosh IM0, open up some templates,

  • and we're about to see is this.

  • Here's a little web application that I made in advance.

  • It's in a folder called Frosh IM0, which has a template subdirectory, inside

  • of which are a whole bunch of web pages.

  • And you can probably infer what they are used for.

  • Index is probably the default. Success has something

  • to do with things going right.

  • Failure is probably the opposite.

  • And we don't know yet what layout.html is, and an application.py.

  • That's it.

  • So let's actually see what index.html looks like.

  • And that's the following.

  • In index.html, it looks like we have a whole bunch of HTML.

  • And I've cut off deliberately the first couple of lines.

  • But what's an H1 tag?

  • AUDIENCE: Header.

  • DAVID MALAN: Header, so it's like a big bold piece of text.

  • So "Register for Frosh IMs" looks like the main text atop this page.

  • Form, action, register, method, post, we saw this briefly when we re-implemented

  • Google a few weeks ago.

  • So here, "action" means that when you click Submit,

  • this is going to be submitted to the current domain slash register.

  • And it's going to use a method called Post.

  • So we didn't talk about this in detail last time, but it turns out

  • there's at least two verbs to know in the web world--

  • Get, which puts everything you type in into the URL, and Post, which,

  • in short, does not.

  • It hides it sort of deeper in the envelope.

  • So based only on that definition, whereby recall that Google uses Get.

  • If I go to Google dot com slash search question mark q equals cats--

  • and hopefully they're doing better today than last time.

  • OK, so notice the URL here--

  • I have to stop pulling up Daily News.

  • So notice the URL here has my search query.

  • Why might it not always be a good thing to put

  • into the URL what the user typed in?

  • AUDIENCE: Cause it's like a password.

  • DAVID MALAN: Yeah, if it's your password,

  • you probably don't want it showing up in the URL.

  • Because maybe someone nosey walks by and can just

  • read your password off the URL.

  • But more compellingly, a lot of browsers have autocomplete these days,

  • and they remember your history.

  • So it would be a little lame if your little sibling, for instance,

  • could just click the little arrow at the end of this window

  • and see every password you've typed into websites.

  • You could imagine this not being good for uploading content like photos.

  • Like, how do you put a photo in a URL?

  • That doesn't feel like it would really work, though technically you

  • can encode it as text.

  • Credit card information or anything else,

  • I mean anything resembling something private or secure to you,

  • probably don't want cluttering the URL bar

  • because it's going to get saved somehow.

  • When you use incognito mode though, for instance, that kind of stuff

  • is thrown away.

  • But this is just bad practice to force your users to use a mode like that.

  • So Post does not put it in there.

  • And so if Google used Post, which they don't for their search page instead,

  • we would appear to be at this URL, just slash search, no question

  • mark, no q, and no cats, but the query can still be passed in.

  • It's just kind of, again, deeper inside of the envelope.

  • So long story short, I chose to do exactly

  • that just because with Frosh IMs, because we don't really

  • need to be storing all of the freshmen's names, and email addresses,

  • and dorms in people's URL bars unnecessarily.

  • So input name equals name, type equals text.

  • This is going to give me a text box, just like q for Google, for someone

  • to type in their name.

  • Select-- it's kind of a weird name, but what does a select element give you

  • visually on a screen, if you recall?

  • Yeah?

  • AUDIENCE: It's like a dropdown bar.

  • DAVID MALAN: Yeah, it's a dropdown menu.

  • So all of the items in that menu are going to be drawn from these Harvard

  • freshman dorms here.

  • And then down at the bottom of this file, if I keep scrolling,

  • notice there's one other input whose type is Submit.

  • And what does a input whose type is Submit

  • look like on the screen, if you recall?

  • AUDIENCE: It's a button.

  • DAVID MALAN: Yeah, it's just a button.

  • That's it.

  • And you can style it to look differently,

  • but it's just a button by default. So long story short, this web application

  • gives me a form via which frosh can register for intramural sports.

  • And I can see this as follows-- if I go into Frosh IM0,

  • and I simply do Flask run, I'm going to see my same URL as before,

  • but now a different application is running on the same port.

  • Here's what it looks like.

  • It's super simple, super ugly, but it does, indeed, have a text box.

  • It's got a dropdown.

  • And it's got a Register button.

  • And now with the world suddenly got more interesting,

  • because now I have not just static content, like "hello, world"

  • or "I am Mark."

  • I actually have something interactive for the user to do.

  • And if he or she fills out this form now, clicks Submit, two

  • or three weeks ago, we just punted completely,

  • and we let Google handle the user submission.

  • But now we have Python in a programming language that can receive,

  • inside of the same envelope, the user's query for cats

  • or the user's name and dorm.

  • And we can actually do something with it.

  • So this program doesn't do all that much with it yet.

  • If I go in here and zoom in, and I register David from Matthews and click

  • Register, notice what happens.

  • I do end up, as promised, at slash register.

  • And I'm told "You are registered," well, not really.

  • And that's because this is version 0.

  • It actually doesn't do all that much.

  • What does it do?

  • Well, let's go back and try to be less cooperative.

  • So I just reloaded the page.

  • It's still asking for my name and dorm.

  • You don't need to know that information.

  • I want to keep it private.

  • I just want to anonymously register for a sport, whatever that would mean.

  • Register-- OK, I caught it.

  • Notice that the URL is still slash register.

  • But I'm being yelled at for not providing my name and dorm.

  • All right, so fine, I'll give you my name.

  • But I don't want you to know where I live, so I'm just going to say David--

  • Register.

  • And it's still catching that somehow.

  • So only when I actually give it a dorm and a name, like David from Matthews,

  • and click Register, does it actually pretend to register me.

  • So what does the logic look like?

  • In just English pseudocode, even if you've never written Python,

  • what kind of pseudocode would be in application.py for this application?

  • AUDIENCE: If there is no text, provide error message.

  • DAVID MALAN: Perfect, if there is no text provided,

  • provide this error message instead.

  • And so let's take a look at how that's implemented.

  • In Frosh IM0, in addition to my template,

  • I again had this application.py.

  • And let's see what's new and what's different.

  • So first, this is mostly the same as before.

  • I just added one other thing in here, Request,

  • for reasons we'll see in a moment.

  • Here is the line of code that says, hey, Python,

  • give me a web application called app.

  • Hey, Python, when the user visits slash, render the template index.html.

  • That's how I got the form.

  • But this is the interesting part.

  • Let me zoom out slightly.

  • These lines of code are a little more involved,

  • but let's do the one at a time.

  • This first line, nine, is saying, hey, Python--

  • or specifically Flask-- when the user visits slash

  • register using the post method, what do I want to call?

  • Just to be clear, what function?

  • AUDIENCE: Register?

  • DAVID MALAN: Register-- so again, the only relationship

  • here, even though the syntax looks a little cryptic, is this says,

  • hey, server, when the user visits slash register,

  • call the function immediately below it called Register.

  • And then what does that function do?

  • Well, here is the logic that you proposed verbally a moment ago.

  • If not request dot form dot get or not request dot form dot

  • get dorm, name and dorm, then return failure.html, else

  • implicitly return success.html.

  • So the only part that's a little new and different here is 11, line 11.

  • Because in C, you would have to use the exclamation points.

  • You would have to use vertical bars for Or So some of that

  • syntax is a little different.

  • But this works as follows--

  • there exists a function called Get that is inside a special variable called

  • Form that is inside a special variable called Request that I have access to,

  • because I imported it up here.

  • And that function, Get, checks inside of the virtual envelope

  • for a field called Name that would have been populated in the envelope

  • if a user typed his or her name.

  • And if it exists, it returns it, quote-unquote, "David," quote-unquote,

  • "Maria," or whoever it is that's registering, but if not, inverts it.

  • So if not a name, or if not a dorm, go ahead and spit out failure.html.

  • So what does failure.html look like?

  • Well, failure.html just has this hard-coded message,

  • "You must provide your name and dorm."

  • And now at the risk of introducing one too many languages at a time here,

  • there is another one in here.

  • These funky curly braces and percent signs

  • are what's called a templating language.

  • But before we explain what that is, notice at the top of this file

  • is mention of another file, layout.html.

  • That

  • We've not seen this before.

  • In the past, we've just had full and complete index.html files

  • or zuck.html files.

  • But what was true a moment ago about index.html and zuck.html

  • from our last example?

  • Let me go ahead and quickly open those again.

  • Index.html, recall looked like this.

  • And zuck.html looked like that.

  • What do you notice in layman's terms about the two?

  • AUDIENCE: [INAUDIBLE] is mostly the same.

  • DAVID MALAN: Yeah, they're almost identical, right?

  • They seem to differ only in their titles,

  • obviously, and in the body's content.

  • But all the other structure is identical.

  • And to be fair, there's not that much in red there.

  • There's not too many tags.

  • But I mean, I literally, in front of you, copied and pasted this.

  • And generally, that is already a step in the wrong direction.

  • And so there's an opportunity here.

  • There's a problem to be solved.

  • And we've done this in the past, right?

  • In C, if you were to just blindly copy and paste code

  • you need in multiple places, that's kind of dumb.

  • It's kind of messy.

  • It's hard to maintain.

  • Rather, you should probably be defining it as a function

  • that you call in multiple places.

  • Now this is not a programming language, so there's

  • no comparable notion of a function.

  • But because it's a markup language that just has hard-coded values,

  • you can think of this as kind of being a template or a mold,

  • like put something here, and then maybe here, put something else here.

  • So again, if you think of the physical world

  • as having templates, or again, like a mold into which you

  • pour specific values, this is kind of what we're talking about.

  • And that is what layout.html is in this Frosh IMs example.

  • I've not opened it until now, but here is, somewhat cryptically,

  • an example of layout.html.

  • And notice, it's got the doc type.

  • It's got HTML head, title, some other stuff up there body.

  • But then it has this placeholder.

  • And I'll admit it, the syntax is sort of annoyingly cryptic,

  • but this is just saying put something here.

  • And that's all.

  • What are you putting there?

  • Well, if I go back to failure.html, notice that it works as follows.

  • Failure.html conceptually extends this template.

  • It borrows that mold, called layout.html.

  • And then notice the same keywords here, block body and block.

  • This just means plug this into that file.

  • And this allowed me to break my habit quickly

  • of just copying and pasting everything, even though the format of these files

  • is almost identical.

  • So if I go back now to application.py, notice

  • that this program does spit out either index.html or failure.html,

  • or success.html.

  • So it would have been pretty lame to copy and paste my code three times.

  • That's why I took the time to create a fourth file, layout.html, just

  • to factor out everything that's common.

  • And the upside of this, too, means that all of these pages

  • structurally look the same.

  • And if I had like a fancy logo on my website

  • and a nice brand to the web site, all of my pages

  • would look the same except for a message that changes in the middle,

  • say, of the page.

  • And so this, then, is Frosh IM0.

  • Any questions on how this now looks?

  • All right, so we have a couple of other opportunities here.

  • I would propose that it would be kind of interesting to actually remember

  • that the user has registered, instead of just

  • pretending by spitting out a hard-coded value, like "You are registered."

  • Well, not really, because I'm not doing anything with their name or dorm.

  • So maybe we could start storing that in memory

  • and see who is registered for the site.

  • It would be even cooler if, like in my day way back when I implemented

  • the actual Frosh IMs website, you could email someone when he or she registers

  • to confirm that they're registered.

  • Or better still, why don't we actually save it to a mini database,

  • like a CSV file, that I, like the person running Frosh IMs,

  • can actually open in Excel, or Numbers, or Google Spreadsheets, or the like.

  • So before we to get to that, let's take our five-minute break here.

  • And we'll come back and solve exactly those problems.

  • So we are back.

  • And so I thought today would be opportune,

  • since you might have been wondering who Stelios

  • is who has been our example in quite a few of our memory examples.

  • But visiting from Yale University today, one of our head TAs there, Stelios.

  • STELIOS: Hi, everyone.

  • AUDIENCE: We love you!

  • [APPLAUSE]

  • STELIOS: Yale is on break, so I said, why not come by?

  • Yeah, it's glad to see you.

  • I've been in here before many times.

  • It's a beautiful space.

  • And, yeah, come by and hi after lecture.

  • DAVID MALAN: So glad to have you.

  • Thank you, Stelios.

  • So, it was brought to my attention, since I

  • wasn't focusing so much on my logs in the terminal window, which

  • record all of the HTTP requests that you get during a server running.

  • And this is a screenshot of my terminal window from just a little bit ago.

  • And you'll recall that I visited slash, and then I tried to register.

  • But in between there, someone in the audience,

  • apparently, or on the internet, tried to visit slash was up,

  • using Get in their browser.

  • I scrolled past a few other inputs from the internet.

  • But the more shareable ones were these here--

  • bro slash David and slash nice.

  • So that was the last one before I killed the actual server.

  • And this is because, even though I'm listening on a nonstandard port, 8080,

  • that domain name, I did share my workspace publicly so that anyone could

  • access it while the server is running.

  • And if you happened to be here physically or tuning

  • into a live stream, it's obvious that I'm

  • advertising now publicly that port 8080 is where we've been spending our time.

  • But if we turn back now to Flask and maybe minimize our logs moving forward,

  • let's consider how we can actually now remember that users are logged in.

  • So in fact, let me go ahead and demonstrate among today's examples,

  • Frosh IMs1, by running Flask run.

  • And then I'm going to go to the same URL as before up here.

  • And we'll see this time, that if I go ahead

  • and register as David from Matthews--

  • Register, notice now that instead of just going to slash register,

  • I changed things a little bit.

  • And I'm going to slash registrants, because there I

  • seem to have some HTML that generates a bulleted list of whoever

  • has registered.

  • And so now let me go ahead here and go back, perhaps, and register

  • let's say Maria from Apley Court--

  • Register.

  • And now we have two.

  • Moreover, if I just reload the page, notice that this information persists.

  • So how is this actually working?

  • Well, let's go ahead and take a look inside of application.py for Frosh IMs1

  • dot--

  • for Frosh IMs1.

  • So what do we have inside here?

  • So as before, I'm configuring my app with a line like this,

  • like, hey, Flask, give me an app.

  • And then this, I claim, is my registrants.

  • So this is just a comment in Python, the hashtag registrants.

  • Students equals open bracket close bracket represents what, though?

  • AUDIENCE: List.

  • DAVID MALAN: A list, yeah, it's an empty list.

  • It's like an empty array.

  • But unlike in C, where arrays can't grow or shrink,

  • in Python lists, which are similar in spirit to an array,

  • can actually grow and shrink dynamically.

  • So if you want an empty one, you literally just

  • say, give me an empty one.

  • And then we'll figure out the ultimate length later.

  • And so what's compelling about this on line 7,

  • is that I have a variable now called Students,

  • that's initialized to an empty list.

  • But it's now in the web application's memory.

  • Because recall that when we run Flask, I don't immediately

  • get back to my prompt.

  • The program doesn't just run and then stop.

  • It just keeps listening, and listening, listening,

  • waiting for more of these envelopes to come in.

  • As such, as these various functions get called--

  • index, or registrants, as we'll see, or others--

  • they all have access to this global variable, in this example, Students.

  • And so any of them can just put more, and more, and more data

  • inside of Students.

  • And so here, if I go ahead and do this--

  • let me go ahead and show that in the user visits slash,

  • we just return index.html.

  • Otherwise, if they visit slash register, notice

  • that I've actually got some interesting logic going on this time.

  • So if the user visits slash register via Post--

  • and the only way thus far we've seen that this could happen

  • is if the user does what?

  • How do you do something via Post?

  • AUDIENCE: You submit.

  • DAVID MALAN: You submit a form.

  • So Get, we humans can simulate really easily.

  • If you just go to a URL, by typing it into your browser,

  • you are by default using Get.

  • You can't do the same nearly as easily for Post.

  • You only have access to the URL bar.

  • But if you have a web form, like the one in index.html

  • with the Dorm dropdown and the Name textbox,

  • you can submit via Post, which is how this route can apply just

  • to that particular route.

  • So here on line 21, I'm saying, hey, give me a variable called Name,

  • and put in it whatever the user typed into the Name field.

  • Give me the same for the Dorm.

  • And so we notice, even if it was a big dropdown of items,

  • the user is only selecting one of those.

  • And so we're getting back just this one value.

  • And then here is a little sort of Pythonic-type logic.

  • If not Name or not Dorm, which is kind of nice.

  • It's a little terse, and it would have looked strange a few weeks ago,

  • but now it looks better, perhaps, than it would have in week one

  • in C. Then go ahead and return failure.html.

  • If we're missing the name or the dorm.

  • Meanwhile, if that's not the case, and we've not returned a failure,

  • go to do this, students dot append and then this F-string.

  • So dot append, if you don't recall--

  • and you might not recall, because I don't remember if we showed you--

  • is a method or function built into a list that

  • allows you to literally append a value to a list called Students.

  • So this is how, in Python, you grow an array.

  • You just append to it and the program will figure out

  • the length of this list.

  • This F-string just means here comes a formatted string, similar in spirit

  • to print F, but the syntax is a little different.

  • And the string I'm forming here is so-and-so from such-and-such,

  • so Name from Dorm.

  • And the curly braces inside of a format string or an F-string

  • means that we should plug those variables into that F-string.

  • And then lastly, this is a new feature.

  • You can return not just render template, you

  • can literally return redirect and the path

  • to which you want to redirect the user.

  • And take a guess.

  • If you call redirect slash registrants, what

  • does Flask, because Flask gave us this redirect function,

  • put inside the envelope for us?

  • AUDIENCE: A new address.

  • DAVID MALAN: A new address-- and what kind of status code?

  • AUDIENCE: 301.

  • DAVID MALAN: Like a 301--

  • we saw that a couple of times ago.

  • 301 means redirect the user.

  • So this function handles all of that for us.

  • We don't have to know or worry about how those status codes are actually

  • generated.

  • Meanwhile, slash registrants is super simple, but it does

  • have one nice new feature.

  • So slash register, to which the form submit, ultimately does all this stuff

  • and then redirects the user to slash registrants, just because.

  • And it's kind of better designed if this route is only

  • used for saving information, and this route

  • is only used for seeing information, because this way

  • you can visit it via Get as well.

  • Notice that I'm returning registrants.html.

  • But I'm doing a little something different this time.

  • What is different about line 16, vis-a-vis all of our other render

  • template calls before?

  • AUDIENCE: Students equals.

  • DAVID MALAN: Yeah, students equal students, which is a little strange.

  • But we know that one of those values is referring to this list here.

  • And so this is an example of Python supporting named parameters.

  • It turns out that if you want to pass data into a template,

  • you can put a comma and then the names of the values you want to pass in.

  • Index didn't need this.

  • Failure didn't need this.

  • Success didn't need this, because it's all hard-coded.

  • But Registrants does.

  • Based on what we saw, it's going to generate a bulleted list of like David

  • from Matthews and Maria from Apley Court.

  • So we kind of need to know who those students are.

  • So, OK, registrants.html comma, students shall be the named parameter.

  • And the value of it shall be the list up here.

  • So the right-hand side is a variable, or a value

  • that must exist in the current program.

  • And the left-hand side is a variable that's

  • going to be inside of, we'll see, registrants.html.

  • So let's open registrants.html, because the other templates, honestly,

  • aren't that interesting.

  • Index.html is just like the web form with the dorms and the name field.

  • Failure just says, sorry, you must provide name and dorm.

  • Layout is just the similar web structure as before.

  • So the only new file here, besides the changes to application.py,

  • are in registrants.html.

  • This file, as before, extends a layout.

  • So that's the mold that it's using.

  • And it's going to fill in the following block for the body.

  • So again, this is just specific to the templating technique,

  • just to clean up the code.

  • But the real interesting stuff is here.

  • This is kind of sort of HTML, but kind of sort of not.

  • So what does this look like?

  • AUDIENCE: Python code.

  • DAVID MALAN: Yeah, it kind of looks like Python code.

  • And it's technically not.

  • And I realize this is this awkward part in the semester,

  • maybe like most of the semester, where we introduce

  • all these darned things at once.

  • But this is a language called Jinja--

  • J-I-N-J-A-- that is a templating language.

  • And you'll see that word in documentation and so forth.

  • It's a very lightweight language for just displaying information.

  • It gives you some loops.

  • It gives you some conditions.

  • And it pretty much is Python code.

  • You can think of it that way, but it's not necessarily identical.

  • So for now, you'll see by example what we can do with it.

  • So here, we have a Jinja template that says, "For student in students."

  • This is very Python-like.

  • So "For student in students" means iterate over students,

  • and call each student along the way "student."

  • So with this, I needed to call students, because it's passed into my form.

  • This could be foo, or bar, or S, or whatever.

  • It's just a loop.

  • And then you can perhaps guess what this line does,

  • even though it's a little cryptic.

  • On line 7, I have some kind of familiar HTML,

  • familiar only insofar as for a few seconds a couple of weeks ago,

  • we showed you a bulleted list in HTML, which had a bunch of Li-- list items.

  • But take a guess.

  • What is line 7 probably doing, if you had

  • to guess, based on what the output of this program was?

  • AUDIENCE: Print [INAUDIBLE].

  • DAVID MALAN: Printing what?

  • AUDIENCE: Printing the students.

  • DAVID MALAN: The individual students-- so

  • remember that the Students list is just a list of strings, so-and-so

  • from such-and-such, so-and-so from such-and-such a place.

  • So, if we induce this kind of loop, iterating over that variable.

  • And on each iteration, we spit out a new link list item, a new list item,

  • like in other words, a new bullet, a new bullet, a new bullet, each time

  • printing out just the name of that value,

  • we're going to get a bulleted list of students.

  • And sure enough, the HTML might not be pretty

  • because it's being generated this time by a human.

  • But this is the HTML.

  • If I view Chrome Source for that page, notice that I've

  • got all this stuff from my layout.

  • Down here, meanwhile, I've got ul and ul,

  • which I did hard-code into that file.

  • But these are not hard-coded anywhere.

  • They were dynamically generated.

  • And this is now really the first evidence of, not just

  • the logic within our Python-based web application,

  • but also the ability to generate content back to the user.

  • And if I kept running the server and kept

  • having people submit, and register, and register,

  • that list would just get longer, and longer, and longer.

  • And the proctor or whoever is actually managing

  • the intramural sports can actually look at that list

  • by going to slash registrants and know whom

  • to contact, at least if we asked for more personal information

  • like emails and the like.

  • So any questions then on this example?

  • All right, so it's in example 2, where now we recreate the website

  • that pretty much I implemented back in 1997 or 1998,

  • albeit in a different language, that actually allowed freshmen

  • to register for intramurals.

  • And we can do that as follows.

  • If I go into Frosh IMs2, and I do Flask run--

  • I'm going to now reload that app.

  • And now I'm asking for one other thing.

  • So I made the form a little bigger by asking for an email address.

  • Because this time, I'm actually going to try sending an email.

  • Let me go back over here to the file.

  • And let me minimize this to make room for Frosh IMs2 application.py, which

  • does the following.

  • So I have some mention of password here, but more on that in just a bit.

  • And notice that up here I have a new import, not to mention OS.

  • Notice up here-- let's see.

  • Notice up here, we have import smtplib, so SMTP, Simple Mail Transfer Protocol,

  • which happens to do with email.

  • And that's because this example works as follows.

  • In slash, we just return that template, index.html.

  • If instead you do register, notice what actually happens this time.

  • And I want to move this up here.

  • There we go.

  • So now we have this file here-- this method here--

  • that operates as follows.

  • If the user tries to register via Post, call this function.

  • Get their name.

  • Get their email.

  • Get their dorm, and then just a little bit of a sanity check

  • that's not complete now, because I'm just asking,

  • like before, if not name or not dorm.

  • But how do I also make sure that this user has given me their email address?

  • AUDIENCE: [INAUDIBLE].

  • DAVID MALAN: Yeah, so if not name, or not email,

  • or not dorm-- now I've improved upon this example versus the last

  • by also checking for their email address.

  • And if they don't provide one of those, we say failure.

  • Otherwise, what is this line 23 do?

  • AUDIENCE: Sends its message?

  • DAVID MALAN: It sets a message, a variable called

  • Message, equal to quote-unquote, "You are registered."

  • The next line here is a little cryptic, and you'd only

  • know this from reading the documentation,

  • like I did when writing this example.

  • On the left-hand side I have a variable called Server.

  • This time it's not a web server, it's an email server,

  • to which I want to connect.

  • Specifically, I want to use this library, called smtplib.

  • It's SMTP functionality, Simple Mail Transfer Protocol,

  • to connect to an address that you might not have explicitly seen before,

  • but you can probably guess whose server I'm connecting to on TCP port 587.

  • Long story short, even though most of us, if you use Gmail,

  • just go to Gmail.com, and you start using it,

  • and it appears to be a port 80.

  • Underneath the hood, anytime you compose a message

  • and click Send or send an archive, what is happening

  • is code like this at Google.

  • They're connecting to their own outgoing mail server,

  • called an SMTP server, which happens to be this address.

  • They're connecting to it using TCP port 587, because it's not a web page.

  • It's mail, so it has its own unique number

  • that humans decided on years ago.

  • This line here, 25, start tls, this turns on encryption

  • so that this way, theoretically, no one between you

  • and Google can see the email that you're sending out to their server.

  • And then I hard-coded a few values, here which

  • wouldn't be best practice in general, but this

  • is just for me to register some first years for Frosh IMs.

  • So what happens next?

  • On line 26, this is the line.

  • According to this library's documentation,

  • via which I can log in as username jharvard@cs50.net, passing

  • in his password.

  • So recall a couple of times ago, I think I

  • mentioned that there are these environment variables, when

  • we talked about programs memory space.

  • Environment variables are like these global values that aren't in your code

  • but you do have access to.

  • So this just says get from the environment,

  • from somewhere in the IDE, JHarvard's password.

  • So I don't have to hard-code it and broadcast it on the internet.

  • Meanwhile, line 27 does kind of what the function says.

  • This says, using this server, Gmail, send mail from jharvard@cs50.net

  • to this email address with this message.

  • And this message, as you've noted, is just, "You are registered."

  • And where does this email variable come from, just to be clear?

  • To whom is this email going?

  • AUDIENCE: To the user.

  • AUDIENCE: The student.

  • DAVID MALAN: The student who registered via the form,

  • because we got their name, email, and dorm.

  • Assuming he or she typed in a legitimate email address,

  • it's being passed to the second argument to send mail, and then it's being sent.

  • And then lastly, render template success.html, and voila.

  • So now you are about to experience either one of the cooler demos

  • we've done in class or one of the more embarrassing failures.

  • If you would like to play along at home, go to tinyurl.com/fridaycs50.

  • That's a lot easier to remember.

  • Tinyurl.com/fridaycs50-- Enter, that should redirect you via our old friend

  • HTTP 301, should put you at this form.

  • And then I will play along at home, too.

  • David from Malan, actually, I'm going to tell it my address is John Harvard's.

  • He will be from, let's say, Pennypacker--

  • Register, and registered really, which hopefully you shall soon see, too.

  • And meanwhile, I get a security alert in my Google accounts,

  • because everyone's using it.

  • But that's OK.

  • I am registered at JHarvard.

  • And, oh, my goodness, all of these examples,

  • OK, and the errors that we'll soon see--

  • we'll soon explain-- so what did I just get?

  • If you, like me, check your mail in some number of seconds from now,

  • you should see an email from jharvard@cs50.net with the message,

  • "You are registered" that was sent directly to me, or hopefully to you.

  • Now, at least two of you will not get this message,

  • because according to my bounced mail, three of you

  • have mistyped your email addresses into the example.

  • And so they're bouncing back to me.

  • So if you don't get it, simply try again.

  • So what actually happened here?

  • So I actually wrote code clearly, in this case, that via application.py had

  • this route slash register that didn't just save things in a variable

  • this time.

  • It actually tucked them up into a special type of library

  • that actually knows how to send mail.

  • And this is literally what I did back in the day.

  • It didn't occur to me--

  • actually, it might have occurred to me, but I

  • didn't know in 1997 what a database was or where we could actually

  • store the information.

  • So I'm pretty sure, the very first version of registrations

  • online at Harvard for Frosh IMs were to literally just send

  • the proctor an email, who was responsible for that intramural sport.

  • And it was good enough.

  • They could just use their inbox as essentially their database,

  • and know who had registered.

  • Eventually though, we were able to improve upon this

  • and actually save things in a lightweight database.

  • I still didn't know SQL, and I didn't know how to do things more fancily.

  • But I didn't know what a CSV file was.

  • I had Microsoft Excel, or Numbers more recently, on my computer,

  • so I can open up spreadsheets.

  • And so it turns out, that if we instead look up

  • say Frosh IMs3, which is our final version of the Frosh IMs

  • suite of examples, I actually went ahead and did this.

  • In this version of the program--

  • it's a little cryptic, but I figured this

  • out just by reading on Python's documentation and how to use CSVs.

  • And I came up with the following.

  • So as before, on line 12, if not name or not dorm--

  • so I've reverted to the old syntax, because I'm not

  • using email address for this example--

  • then I go ahead and return failure.htlm.

  • But the new code here, instead of email, is this functionality.

  • So here I have file, which is a variable, gets stored--

  • gets the return value of Open.

  • So this is a function in Python that's similar to fopen in C. They just

  • kind of clean up the name here.

  • It open a file called registrants.csv.

  • And what do you think the quote-unquote "a" means?

  • We probably-- you didn't use "a."

  • You used a different letter in p-set 4.

  • AUDIENCE: [INAUDIBLE].

  • DAVID MALAN: What's that?

  • AUDIENCE: R or W?

  • DAVID MALAN: We used R or W for read or write.

  • Turns out a is a little different, which makes sense in this case.

  • AUDIENCE: Append.

  • DAVID MALAN: OK, thank you.

  • OK, it's append.

  • And append make sense here because write, by default, literally

  • overwrites the file.

  • It creates a new file.

  • Whereas, append literally does that.

  • It adds a line to the file, a new line to the file, which

  • is good if you want to have more than one person ultimately saved

  • in the file.

  • You want to remember everyone else by appending.

  • So this says, hey, Python, open the file in append mode,

  • and store it in a variable called File.

  • This is a line of code that uses some syntax we didn't quite see in C,

  • but we're declaring a variable called Writer using the CSV library, which

  • I've imported at the top of this file, similar to importing the mail

  • library in the last one.

  • And it has a function called Writer that I can pass in an open file.

  • And this is just a special library that knows

  • how to put commas in between values, knows how to save things,

  • knows how to escape things if there's actually commas in your file,

  • and so forth.

  • And then this line is a little funky.

  • But it does use some building blocks from earlier--

  • writer dot write row-- writer write row.

  • So this kind of does what it says.

  • This says, use the library to write a row to the open file.

  • What you want to write?

  • Now if there's deliberately these additional parentheses here,

  • turns out this function is supposed to take a tuple.

  • A tuple is zero or more values separated by commas,

  • which is kind of nice because it's kind of similar in spirit

  • to a set of columns.

  • Like a tuple is something comma something comma something.

  • That is exactly what we want to put in a CSV, something comma something comma

  • something.

  • Because if you're unfamiliar, a CSV is just a file where all of the values

  • are separated with commas.

  • And if you open it in Excel, or Numbers, or Google Spreadsheets,

  • each of those commas demarcates a barrier between various columns.

  • So this says, go ahead and write a row to the CSV,

  • containing the student's name and the students dorm.

  • And then close the file and return Success.

  • So at the risk--

  • there's like a 30-second internet delay, which

  • means we can keep this clean for about 30 seconds.

  • Let me go ahead and run this example here in Frosh IMs3 and do Flask run--

  • Enter.

  • And if you'd like to go ahead to my same URL, tinyurl.com/fridaycs50,

  • that will take you back to a slightly older version of the form,

  • no email address, so make sure you hit reload.

  • And you should see just this version, name and dorm.

  • And if I wrote the code right, we should all

  • be able to register in a file called registrants.csv in my IDE.

  • You're not going to get an email this time, because we

  • ripped that functionality out.

  • But this Register page claims that it's working.

  • So if you'd like, take a moment to do that.

  • I'll go back to the IDE here.

  • Looks like a lot of registrations coming in, so that's pretty cool.

  • These are the logs here.

  • And so you can see everyone visiting the site and hitting Register.

  • That's actually a lot of people registering.

  • That's pretty cool.

  • I'm going to briefly turn off the screen this time

  • and see who has registered by going into this directory.

  • This is-- OK, I'm going to go into Frosh IMs3 is what I'm doing here.

  • I see registrants.csv.

  • OK, let's just scrub this.

  • [LAUGHTER]

  • OK, David Malan 2.0 registered, great.

  • All right, I'm going to download this file.

  • I think it looks pretty clean.

  • Let me download this.

  • And I'll show you what I'm doing in just a second.

  • But this is the best demo ever, from what I can see.

  • All right, and let's make sure I didn't miss this here.

  • Uh huh, OK, some of you are just hitting--

  • Brandon was just hitting Submit a lot, apparently.

  • All right, I don't think I'm going to regret any of this.

  • OK, we're good.

  • All right, so what did I just do?

  • We're back.

  • So now that we've run everything through the censors, what I've noticed

  • is that, oh, I have a registrants.csv file in the same directory.

  • And that was what was getting appended to each time.

  • Meanwhile, if I go ahead and download this

  • file by doing registrants.csv and then Download.

  • Or I could just open it in the IDE to see the actual rows and columns.

  • Let me actually do that real quick.

  • So you'll see this file here.

  • But it's a little hard to see.

  • So I'm going to deliberately close it, because I downloaded it earlier.

  • And I can actually open it in Excel.

  • And if in Excel I just expand my columns, each of these columns

  • represents the gap between a comma.

  • Brandon was apparently trying to make his name very big and bold,

  • but that doesn't work in CSV files.

  • Montreal is apparently the best.

  • A lot of first names--

  • more Brandon-- unknown, OK--

  • there is that one I mentioned, someone's dad.

  • Maybe someone's dad is here today, OK.

  • All right, we, MTL is the Best, John Harvard, John, Olivia, Batman, Kyle--

  • [LAUGHTER]

  • DAVID MALAN: OK, there's Worthy of Wiggles--

  • now it's getting a little strange--

  • faces, buttface, OK, that made it through.

  • I didn't notice.

  • David, I'm scared, OK.

  • [LAUGHTER]

  • So we finally have, thanks to programming,

  • the ability to actually keep some of this data around.

  • And so this ultimately allows us to now start

  • making applications that are truly interactive.

  • And they actually allow us to store information and retrieve

  • that information, ultimately.

  • And it all reduces to some of these simple paradigms.

  • And now, absolutely, there's a whole bunch of cryptic syntax involved.

  • And there's some new ideas along the way, things like tuples

  • and things like routes.

  • And I didn't use the word before, technically this at sign denotes

  • something called a decorator.

  • But as with C, back in those early days, keep in mind

  • that once you start noticing these patterns,

  • even if you don't appreciate everything or understand everything

  • from the get-go, you can kind of iteratively

  • get more comfortable with the material.

  • If you kind of take on faith that I don't really

  • remember how this works, but I know that I have to do it now, that's fine.

  • Because if you understand more of the stuff below it,

  • that'll solve the problem for you and get the work done.

  • And as you get more at ease with this, then can you start, through section,

  • and office hours, in the p-set itself, start

  • to really understand some of the nuances here

  • and how it relates or doesn't relate to things we've seen in the past with C.

  • So where are we going with this?

  • Well, with problem set 6, we're going to bridge these several worlds of the web,

  • and of Python, and also of edit distance,

  • and dynamic programming from our Yale lecture a couple of weeks back.

  • And if you're a little behind on some of those topics,

  • or some of today's material wasn't quite on the tip of your tongue, that's fine.

  • Do go back, though.

  • Because realize the past three lectures really now culminate in problem set 6.

  • You will be challenged to go back and re-implement

  • Mario, either the less or the more comfy version, not in C, but in Python.

  • And odds are, you'll be struck for at least two reasons.

  • One, odds are if you did solve it successfully the first time around,

  • even if you're a little rusty, odds are you

  • will solve it much more quickly this time around,

  • even though it's a new language.

  • And you'll see what some idea from C maps to some other idea

  • in Python, just like we did from Scratch to see that same kind of transition.

  • Same thing for Cash or Credit, same thing for Visionaire,

  • or Caesar, or Crack as well.

  • But the icing on the cake is then going to be to not just write code in Python,

  • but write code in Python for a web application that actually does

  • something graphical with a website.

  • So for instance, here we have the more comfortable version of the staff

  • solution to Similarities, one piece of problem set 6.

  • And you'll notice on this web-based form,

  • I'm currently at similarities.cs50.net/more.

  • Your URL, of course, will be different, whether you do

  • the less comfy or more comfy as well.

  • But here we have a web form with two strings waiting to be typed in,

  • two textboxes.

  • And now this form arguably looks a lot prettier than the ones

  • I've been doing today.

  • And because the ones I've been doing today had no what in them?

  • AUDIENCE: CSS.

  • DAVID MALAN: There was no CSS whatsoever.

  • So what I was getting were the pretty old, ugly,

  • 1990s styles defaults that Chrome, and IE, and Edge, and Firefox,

  • and Safari all give me by default. But you

  • can use libraries out there that allow you

  • to make your websites much prettier.

  • So long as you just understand how to generate the markup,

  • you can let someone else style it and take it that last mile for you.

  • So most of the aesthetics of what you see here, the nice navigation

  • bar at the top, the font sizes, the nice gray highlighting here,

  • the fact that this goes all the way to the edge, the fact

  • that there's the same margin over here as there is over here, the fact

  • that the button doesn't look as ugly as it did before, all of that is CSS.

  • And we happen to be using a library called Bootstrap,

  • which is a very popular library that's got a lot of functionality,

  • like forms, to help you style these things.

  • And if I, in this application, type in a string like Harvard and then type

  • in a string like Yale and click Score, what you will see here,

  • a little cryptically-- very cryptically if you're not fully caught up

  • on our lecture from Yale--

  • is you see a matrix at the top here.

  • This is just a grid of rows and columns.

  • The top row of this matrix says H-A-R-V-A-R-D,

  • so obviously the first word I typed in.

  • And on the y-axis it says Yale, Y-A-L-E And what each of these numbers

  • represents is the cost, step-by-step, of converting one string into another.

  • Now that in and of itself is kind of a useless exercise,

  • but the number of steps to convert one string into another

  • rather gives you an estimation of how similar or how different strings are.

  • If there's very low cost to change one string to another,

  • odds are they're really similar.

  • If it takes one step to convert one word into another,

  • odds are they're identical except for one character.

  • Or if the cost is really high, like six, then it takes six steps

  • to convert Harvard into Yale.

  • And that kind of makes sense, because they are really different words,

  • except for maybe the fact that they have an A in common

  • that maybe we can reuse without having to change that completely.

  • So edit distance is a technique that can be solved very slowly and very

  • expensively in the naive way, using essentially a couple of for loops,

  • where you iterate over one string, you iterate over the other string.

  • And you just iteratively, or rather by a bit of recursion,

  • try every possible change to the string.

  • Well, what if I delete this and then add this?

  • What if I add this and delete this?

  • What if I just change this, and then add this, and then delete this?

  • There are so many permutations of adding, and deleting,

  • and editing characters, that it's just a really slow problem, especially

  • when the strings get longer than these.

  • And so what you'll do, if you choose to do

  • the more comfy version of the problem set,

  • is you'll implement this by a dynamic programming.

  • And this matrix up here just remembers, just

  • stores, all of the temporary values that I've so-called memoized along the way,

  • such that if you recall from Benedict's lecture,

  • you just kind of work your way from top left to bottom right

  • to get your final answer.

  • And the fact that that number is relatively big,

  • 6, means that Harvard is not very similar to Yale, at least in terms

  • of its string comparison here.

  • I didn't realize the semantics of that until I said that sentence.

  • So meanwhile-- oh, and then as an aside, if you didn't notice already,

  • at the bottom here is kind of a log.

  • This just shows you, once you've implemented the top here,

  • what it is that has to happen to Harvard in order to turn it into Yale.

  • We have to delete an h, delete this a, delete this r.

  • Then we have to change a letter to y, change another letter to l,

  • and another letter to e, and voila, Yale.

  • But notice, if we do something more similar, like let's say, let's say,

  • suppose we do Mario from p-set one and Maria from the heads team.

  • This is a much more similar string, because it only takes

  • one step to convert one into the other.

  • And so the log is much smaller as well.

  • And so you get an estimation of similarity.

  • But we can take this one step further using different algorithms that

  • may or may not perform as well.

  • So here's the less comfy version of the same problem, whereby now I'm

  • being asked for two files, so not just two strings.

  • You can you do even bigger files in this way,

  • because it's not quite as expensive, and it's a lot easier

  • to show on the screen.

  • So I downloaded, or I whipped up a couple of examples in advance here.

  • I have a file called hello.c, which looks like this--

  • a little flashback from week 1.

  • And then I have another file called hey.c,

  • which is identical except for some word, like, hey comma world.

  • So I'm going to go ahead and do this.

  • I'm going to go ahead and upload hello.c and hey.c.

  • Or I could just click these, and then I could navigate through my hard drive

  • like you might on your Mac or PC.

  • But I'm just going to drag and drop them.

  • And then I have three choices of algorithms.

  • Because if you can think about what a text file is,

  • I don't really know off the top of my head how best to compare them.

  • I can probably tell you if they're identical.

  • I can just use like a while loop or a for loop in C

  • and iterate over every character in the file and tell you True or False,

  • these files are identical.

  • But if there's a little difference, like hey and hello, or maybe some spacing,

  • then I have different options.

  • So what if we compare these files line by line?

  • Should most of the lines in hello.c and hey.c

  • be similar or different, do you think?

  • AUDIENCE: Similar.

  • DAVID MALAN: Similar, except for that one printf line.

  • So let's see what happens.

  • If I go ahead and choose compare lines as my algorithm and click Compare,

  • I see highlighted in yellow, in the user interface, the two programs left

  • and right, hello and hey, with all of the identical lines highlighted.

  • So the fact that there is so much yellow means, OK, these are pretty similar.

  • I'm not slapping a value on it, in this particular case.

  • But I certainly could say that it's all but one of the lines are in common

  • and ascribe it that kind of score.

  • Meanwhile, sentences doesn't necessarily make sense.

  • But if this were an essay, or if you're familiar with sites like Turnitin

  • and so forth, like an English essay, I could upload two different essays

  • and see how many sentences do they have in common.

  • So that even if one sentence is up here and another is down here,

  • because the students used the same quotes or whatnot,

  • I can at least find those by breaking the text up

  • based on periods in an English sentence, which don't

  • exist in quite the same way in code.

  • But what about substrings?

  • Substrings is a more fancy term just to say

  • a portion of a string of length one, or two, or three, or four.

  • And here I have a textbox where I can configure this.

  • So if I want to look for common substrings of length 10,

  • that would be a pretty long string of text that's in both.

  • Compare, and indeed, there's a lot of stretches of 10

  • because they're all so similar.

  • If I instead change this to one, looking for all the common characters,

  • you'll see that almost everything is in common, except for what missing letter?

  • AUDIENCE: Y.

  • DAVID MALAN: Y-- so there's going to be a couple of different ways you

  • can implement this, actually many different ways that you

  • can implement each of these algorithms.

  • But what's key is that by using Python, you're

  • going to have a lot more tools at your disposal.

  • You're going to have different data types like Lists, and Sets,

  • and Dictionaries, if you want to use them.

  • And what you're not going to have to do, as you might have in C,

  • is actually parse out these characters individually.

  • Rather, if you want to split up a file based on its lines,

  • just call a function for that.

  • If you want to actually grab all of the whitespace,

  • just call a function for that.

  • If you want to take a substring of a certain length,

  • just use the right Python syntax for that.

  • And so once you've taken this sort of scaffolding approach

  • of porting some of your C problems to Python,

  • you'll culminate in implementing either of these.

  • We'll wrap a bit earlier today.

  • I'll stick around for questions.

  • Best of luck, and see you next time.

[MUSIC PLAYING]

字幕與單字

單字即點即查 點擊單字可以查詢單字解釋

B1 中級 美國腔

CS50 2017 - 第 9 講 - Python (續) (CS50 2017 - Lecture 9 - Python, continued)

  • 59 8
    小克 發佈於 2017 年 11 月 14 日
影片單字