COLTON OGDEN: All right.
Hello, world.
This is CS50 on Twitch.
My name is Colton Ogden.
I'm joined today by--
KAREEM ZIDANE: Kareem Zidane.
COLTON OGDEN: So apologies if you've
been watching in the live chat.
It took us a little bit to get online.
We're having some difficulties
with a brand new setup.
But it looks so far to my eye that
everything is currently Livestreaming
and looks excellent.
Let me go ahead and make sure I'm
muting everything here on my laptop
that the audio is coming from.
So what are you here
to talk with us about?
You're a regular.
You've been in a couple of times.
We did like a Travis stream.
We did some other stuff.
KAREEM ZIDANE: Yup.
I think this would be my third stream.
Yes.
COLTON OGDEN: Nice, you're a
regular, a veteran at this point.
KAREEM ZIDANE: Yeah, I guess so.
COLTON OGDEN: What are
you talking about today?
KAREEM ZIDANE: We're going to talk a
little bit about Flask today, which
is a micro web framework.
It's used.
It's very popular.
It's a Python framework.
And it's used in a lot
of web applications.
COLTON OGDEN: Nice, nice.
So a lot of people in the chat may have
programmed in Python before, but maybe
not necessarily in the context of web.
KAREEM ZIDANE: Yeah.
COLTON OGDEN: So this is kind of
like a nice entry level sort of way
to get into server side programming
with Python would you say--
KAREEM ZIDANE: Yup.
Yup.
COLTON OGDEN: --as opposed to
maybe like something like Django
would be another technology that
folks might have heard about.
KAREEM ZIDANE: You might say
that Django is similar in spirit.
It's just, I guess, heavier.
COLTON OGDEN: Yeah.
KAREEM ZIDANE: But I'm
not an expert in Django.
But, I mean, yeah, it's
pretty much the same thing.
The job of a web
framework in general is,
you know, facilitating the
process of actually developing
a web app or a dynamic web app.
COLTON OGDEN: Sure.
And this would be server
side as opposed to like maybe
JavaScript, CSS, HTML, stuff that
the web browser actually deals with.
KAREEM ZIDANE: We're going to see a
little bit of HTML and CSS as well.
We're not going to see
JavaScript, but you
could use JavaScript if you wanted to.
Yeah.
I mean, I thought I'd make this as
simple as possible and as focused
as possible.
So, yeah, we're going to be focused
more on the server side of things today
as well as some templating with Jinja.
COLTON OGDEN: Cool.
Awesome.
I can't wait.
KAREEM ZIDANE: Yeah.
COLTON OGDEN: I'm very excited.
We have a few new followers
here in the stream,
so I'm going to give
some shout outs to them.
So thank you very much to
AFMM01, Negative_Nancy, baffoon9,
ZombieRaccoon, [? COBOL ?]
[? 2070, ?] [? Hussam ?] [? Farag, ?]
and [? Igor ?] [? Voltaic. ?] Thank
you so much for following today.
KAREEM ZIDANE: Thank you.
COLTON OGDEN: I'll
transition to your laptop
here so we can see what we're
working with here today.
Yeah.
Why don't you get us started here?
KAREEM ZIDANE: Cool.
So I am inside of my container, yup.
And I thought I would start by talking
about a little bit of the concepts that
were actually a little bit difficult
for me to sort of grasp at first
when I first started learning
about with programming.
And some of these concepts
is, like, what's a server?
What's a client?
COLTON OGDEN: Sure, sure.
KAREEM ZIDANE: Like how do they
communicate with each other?
And the basic idea is that a server is a
piece of software that is just running,
listening for web requests.
At once it receives a web request,
it parses it, processes it.
And then if everything's OK, it responds
with some responses we'll soon see.
COLTON OGDEN: So some program on
somebody's computer somewhere,
it's listening for network
traffic sort of like bits of data
that are sent to it.
It processes them and then
sends back a response.
KAREEM ZIDANE: Exactly, yes.
So, yeah, exactly as explained.
A client, on the other hand,
might be something like a browser
which actually initiates
or makes a web request
and expects a response back from
the server and then, you know,
does something with that response
whether it's, for example, showing
some web page and so on.
And so we're going to actually
see an example of this right now.
So let's actually get started.
So before we actually start, I
just want to explain something
about the protocol that's
being used in this case.
COLTON OGDEN: Sure.
KAREEM ZIDANE: It's the HTTP protocol.
And it's an example of
an application protocol.
COLTON OGDEN: OK.
KAREEM ZIDANE: And we'll
see what that means.
But for two pieces of software
to communicate with each other,
they need to be speaking
the same language, right?
COLTON OGDEN: Right, yeah.
I guess, yeah.
KAREEM ZIDANE: Because, you
know, if some server's listening
for some network traffic
or some requests,
it expects to receive some data, right?
COLTON OGDEN: Yeah.
KAREEM ZIDANE: You know,
if this data is arbitrary,
it's not going to be easy for the
server to sort of make sense of it,
because it's not a human.
COLTON OGDEN: If someone's speaking
French and someone's speaking German--
KAREEM ZIDANE: Exactly.
COLTON OGDEN: --it's highly unlikely
they're going to understand each other
if they don't know the other language.
KAREEM ZIDANE: And so, yeah,
there's an agreed upon language
that they both speak.
And this language is in the form of
the protocol that is called HTTP.
And just to be clear, this is
not a programming language.
COLTON OGDEN: Right.
Right, just sort of a
standardized way of sending--
basically just communication
standard protocol like you said.
KAREEM ZIDANE: Exactly.
And let's actually see exactly
an example of this right now.
So I have just one file
here called index HTML.
And these are the contents.
Let me zoom this in a little
bit so we can see better.
And these are actually the contents
of my index HTML, just a simple HTML--
COLTON OGDEN: Right OK.
KAREEM ZIDANE: --file.
And then I'm going to start an HTTP
server to serve this file for me.
And then I'm going to make a request.
And I'm going to see what I'm
sending and what I'm getting back.
COLTON OGDEN: OK.
KAREEM ZIDANE: Right?
COLTON OGDEN: Cool.
So HTTP server, what
kind of program is that?
Does that comes stock on Linux?
KAREEM ZIDANE: No, HTTP server
is actually a node package.
COLTON OGDEN: OK.
KAREEM ZIDANE: You can install it.
If you have node installed
and NPM installed,
you can install it using
npm install -g http server.
COLTON OGDEN: Ah, OK.
KAREEM ZIDANE: And it doesn't
have to be the HTTP server.
It can be any other static web server.
But this tool is also
actually installed already
on labs, and on the sandbox
environment, and also on the CS50 IDE.
COLTON OGDEN: Can people
watching right now
get access to one of those sandboxes
and mess around with Flask themselves?
KAREEM ZIDANE: Definitely.
Yeah.
If you go to sandbox.cs50.io,
you can choose Flask from here.
COLTON OGDEN: I plugged it in the chat,
everybody, the sandbox.cs50.io link.
If you want to mess
around with Flask, but not
actually have to install it
on your physical machine,
definitely check that out.
Also, lethalshotgg, mdobra71,
and [? mansonjai, ?]
thank you very much for following.
KAREEM ZIDANE: Yup.
COLTON OGDEN: We'll have to come
back to the chat in just a second.
I think maybe once we've gotten started
we can read up all the messages.
We have a few.
We a little bit of a
backlog to catch up to.
KAREEM ZIDANE: Yup.
COLTON OGDEN: But,
anyway, you were saying?
So we have HTTP server.
You set that up using the
node package HTTP server.
KAREEM ZIDANE: Yes.
COLTON OGDEN: So now it's
running on your machine.
So it's kind of listening forever,
right, for network traffic?
KAREEM ZIDANE: Correct.
Yeah.
And for it to be listening, it has
to be listening for on some port.
COLTON OGDEN: Right.
KAREEM ZIDANE: And you
can you can think of--
like people often use an
analogy for this I think.
You know, different ports correspond
to sort of different apartment numbers
in a building somewhere.
COLTON OGDEN: Sure.
KAREEM ZIDANE: So different ports
are used for different services.
And by convention, you
know, HTTP servers listen
for it should be traffic on port
80, or HTTPS traffic on port 443,
or SSH traffic on port 22, and so on.
COLTON OGDEN: So Jerry
makes pizzas in room 80.
And if somebody wants
a smoothie, they're
going to go to Tom's apartment--
KAREEM ZIDANE: Exactly.
COLTON OGDEN: --in room 81.
Or I guess, what's the HTTPS?
KAREEM ZIDANE: HTTPS 443?
COLTON OGDEN: Yeah, they'd go to
room 443 instead of room 80 I guess.
KAREEM ZIDANE: Yeah, exactly.
So, yes, you would be able to send some
data to some port whether it's open
or not.
Maybe you'd get an
error if it's not open.
If it is open and some
other server is listening
on that port for
different kind of traffic,
it's maybe going to give you a bad
response, or ignore you at all,
or it does whatever it wants to do.
COLTON OGDEN: Right.
OK.
So different ports are reserved
for different purposes.
KAREEM ZIDANE: Yes.
And by default, here HTTP server
actually listens on port 8080,
as we can see, right?
So we're expected to go to whatever
IP address of our machine is,
[? code ?] [INAUDIBLE] port.
COLTON OGDEN: Right.
And 127.0.0.1 is usually
shorthand for my own computer--
KAREEM ZIDANE: Exactly.
COLTON OGDEN: --local host.
KAREEM ZIDANE: It's a
loopback IP address.
It's local host.
Yes, it refers to your computer.
COLTON OGDEN: Right.
I'm actually not as
familiar with 172.17.0.2.
KAREEM ZIDANE: So it's a
little bit complicated.
There are multiple IP addresses, because
the Docker container that I'm using
has a different IP address.
COLTON OGDEN: I see.
OK.
KAREEM ZIDANE: And so right now,
it listens on all IP addresses
that this container has, which is the
local host IP address and the Docker
container's IP address.
COLTON OGDEN: I see, OK.
That's pretty cool.
So it makes it accessible from
both your computer and Docker?
KAREEM ZIDANE: Yes.
Yes.
COLTON OGDEN: Nice.
KAREEM ZIDANE: Kind of.
COLTON OGDEN: OK.
So you have the server up right now.
So it says hit control C to stop it.
KAREEM ZIDANE: Yup.
COLTON OGDEN: So it's just a
regular program, a CLI program.
And then now what you're
trying to do is test actually
getting a response from the server.
KAREEM ZIDANE: Yeah.
COLTON OGDEN: So that's
where you're using Curl.
KAREEM ZIDANE: Yeah.
I'm just going to make a
request to that server.
And I'm expecting to get a
response from the server.
And I don't have to use Curl for this.
You can use your web browser.
I'm going to show how to do
this in your web browser.
COLTON OGDEN: Sure.
KAREEM ZIDANE: But for now,
just for the sake of simplicity,
I'm just going to try Curl.
And let me resize just a little bit.
OK.
So local host we said, and then :8080
COLTON OGDEN: OK.
KAREEM ZIDANE: And then hit Enter.
And if you notice up here, the
server actually got something, right?
COLTON OGDEN: Right, yeah.
KAREEM ZIDANE: It appears
to have gotten a--
COLTON OGDEN: Different
colored text, too.
KAREEM ZIDANE: Exactly.
Yeah, get request forward slash, we'll
explain what that means in a moment.
Let's crawl back up here a little bit
and see what our tool actually did.
So the first thing that our tool did
is open the connection to the server.
COLTON OGDEN: Right.
KAREEM ZIDANE: Right?
And then--
COLTON OGDEN: Curl is kind
of like a command line
version of using a web
browser to go to a you URL
almost in a very limited sense?
KAREEM ZIDANE: Yeah.
Curl is, essentially, a tool
that you can use to make--
COLTON OGDEN: Network request--
KAREEM ZIDANE: Requests, yeah.
COLTON OGDEN: --generally speaking?
KAREEM ZIDANE: Yeah.
Let me actually highlight this
so that we can see it better.
So all of the greater than sign
something, this is what is being
or what has been sent already.
COLTON OGDEN: OK.
KAREEM ZIDANE: And
everything that follows
that's prefixed with a less than
sign is actually the response
that we got from the server.
COLTON OGDEN: Oh, that's cool.
OK.
Cool.
KAREEM ZIDANE: Right?
COLTON OGDEN: You can see
the direction of the traffic.
KAREEM ZIDANE: Exactly.
So I highlighted the request
parse, so that it's easier for us
to see hopefully.
And after Curl made a
connection to the server,
it actually sent these lines
that we're seeing right here.
COLTON OGDEN: OK.
KAREEM ZIDANE: So first line
is, you know, get/http/1.1.
COLTON OGDEN: OK.
KAREEM ZIDANE: And what
that means-- so there
are different kinds of HTTP requests.
COLTON OGDEN: OK.
KAREEM ZIDANE: We're going to use a
couple of them today, get and post.
Get is generally used to sort of
retrieve resources or retrieve
information from a server.
COLTON OGDEN: OK.
KAREEM ZIDANE: And in this case, we--
COLTON OGDEN: We're getting some
information from the server.
KAREEM ZIDANE: Exactly, yes.
Literally, yeah, getting
some information from server.
And in this case, by default, since
we didn't specify any path after
the 8080/, it's going to
try to get index.html.
COLTON OGDEN: OK.
KAREEM ZIDANE: Right?
Or the server is going to try to
serve us index HTML by default.
COLTON OGDEN: Right.
KAREEM ZIDANE: So this says,
hey, we're making a get request.
And we're requesting the
slash resource in this case.
Right?
COLTON OGDEN: OK.
So it's like the route.
It's kind of like the beginning
of your hard drive almost,
but in an abstract sense also related to
websites that might have multiple URLs,
like facebook.com/users/comments.
But this would just
be like facebook.com.
KAREEM ZIDANE: You may
think of it as a path
in some structure on your computer.
But it's not always the
case that this is a path.
It can be something
arbitrary [? that's ?] mapped
for something else behind the scenes.
COLTON OGDEN: Yeah.
Yeah, with the routing
and stuff like that.
KAREEM ZIDANE: Exactly, yes.
And so the next bit is HTTP/1.1.
And what this means is that Curl
tries to inform the server that,
hey, I'm speaking HTTP version 1.1 just
to make sure that they both understand
the same version HTTP in this case.
COLTON OGDEN: Not a whole
lot of versions of HTTP.
It looks like they've had a
fairly limited number of versions.
KAREEM ZIDANE: That's fair, but for
the future maybe, like if this changes.
COLTON OGDEN: Yeah.
Yeah.
KAREEM ZIDANE: If some client, or
Curl, or browser, or something else--
COLTON OGDEN: Aren't they
coming out with HTTP/2?
Isn't that a thing?
KAREEM ZIDANE: I think it is.
I don't know much about that.
[INAUDIBLE]
COLTON OGDEN: I thought I heard
about that at some point, maybe not.
KAREEM ZIDANE: Yeah.
I don't know much
about it unfortunately.
I don't know about the differences.
So maybe I should look
this up after and see.
But, anyway, the point
is that this sort of
tries to ensure that they're both
speaking the same version of HTTP,
because different versions can have
different sort of, I don't know,
system of actions, or
statements, or sentences
that they might not understand.
COLTON OGDEN: Sure.
KAREEM ZIDANE: And so this
just tries to make sure
that they're both
speaking the same version.
COLTON OGDEN: OK.
KAREEM ZIDANE: The second line
here host:local host 8080,
and this is what's called
a request header, right?
It's additional data or additional
metadata sent as part of the request.
And it can be useful for some contexts.
And the context here is that
it's not always the case
that you can just have one
server running on one machine,
on the same machine.
In other words, you can have more than
one server running on the same machine.
COLTON OGDEN: Sure.
KAREEM ZIDANE: And this
just tries to make sure
that, hey, I am looking for the
server that's a local host for 8080
specifically.
Because there could be another HTTP
server listening on 8081 OR 8082
or whatever, right?
COLTON OGDEN: Makes sense, yeah.
KAREEM ZIDANE: OK.
COLTON OGDEN: Like email servers, too.
KAREEM ZIDANE: Email servers.
COLTON OGDEN: HTTP servers.
KAREEM ZIDANE: Usually, you
look on port 25 I believe.
COLTON OGDEN: Yeah.
I think that's right.
Yeah.
KAREEM ZIDANE: But, yeah, so this
tries to make it clear that, hey, I am
requesting from this particular server.
There's also the context
of virtual server.
And this is, you know, you can run more
than one server on the same machine.
COLTON OGDEN: Right.
KAREEM ZIDANE: They're
called virtual servers.
COLTON OGDEN: Makes sense.
KAREEM ZIDANE: Because there's also the
physical server, the actual hardware
server, the computer that it's running.
COLTON OGDEN: Like vhosts
to with PHP back in the day?
KAREEM ZIDANE: Yeah.
Exactly.
I think the vhost and virtual
servers mean the same thing actually.
COLTON OGDEN: Yeah, I think
they're the same thing.
Yeah.
KAREEM ZIDANE: The next
line here is a user agent.
And this is also other request header.
And this is just Curl trying to
let the server know that, hey, I'm
Curl that's making this request, not
Chrome, not Firefox, not Safari, not
Opera.
It's Curl version whatever, 761
whatever if that makes sense.
COLTON OGDEN: Yeah.
KAREEM ZIDANE: OK.
Although, I mean, you can technically
sort of change these headers
if you want with some
custom options if you want.
So this doesn't guarantee that
the entity or the software that's
making the request is actually Curl.
I can trick the server into thinking
that what's making the [INAUDIBLE]
is actually Chrome, or
Firefox, or something.
COLTON OGDEN: Kind of
like how Verizon injected
into like mobile traffic
its, like, special headers--
KAREEM ZIDANE: Yeah.
COLTON OGDEN: --which David talked about
it in lecture I think at one point.
KAREEM ZIDANE: I'm not
sure about Verizon,
but I know some internet providers
do that as well, like inject
some data in the headers sometimes.
COLTON OGDEN: Which makes sense.
And [INAUDIBLE] is actually asking,
"are you guys doing a lecture
on Django in the future?"
And that's a good question.
Maybe in the future.
KAREEM ZIDANE: Yeah.
COLTON OGDEN: Maybe some Django
if people want some Django.
[INAUDIBLE] is saying, "Who's teaching
who-- the guy on the right asking
all the questions."
Yeah, I'm very curious about all
that Kareem has to teach us today.
All right.
KAREEM ZIDANE: I'm sure we're all
going to learn something today.
COLTON OGDEN: Oh, yeah.
I'm sure I'm going to learn a lot.
So that was all of the
request information.
And so what's below that is the
response information, right?
KAREEM ZIDANE: There's
actually one more header--
COLTON OGDEN: Oh, I see.
KAREEM ZIDANE: --or
request [INAUDIBLE]----
COLTON OGDEN: OK, right.
KAREEM ZIDANE: --which is
the except star slash star.
And this means that, hey, in the
response that you're sending,
I'm expecting anything that
you send back pretty much.
So a server can send back HTML.
It can send back, you know, JSON data.
It can send back some other binary data.
You know, we can specify,
hey, I'm just expecting HTML.
I'm just expecting JSON.
And in this case, Curl is
expecting pretty much anything.
COLTON OGDEN: OK.
Kind of acts like a filter
almost a little bit?
Will it get rid of MIME types
that don't satisfy that pattern?
KAREEM ZIDANE: So the server
actually should handle this.
The server should see this except
header, like look into your header
and see what you're asking for.
And if the server is able to provide
this kind of response, it should.
Otherwise, it should provide
you with some sort of error
that indicates that I don't have
this kind of resource available.
COLTON OGDEN: Makes sense.
OWLYone, ghostwake,
dotmido, and vivek_chauhan,
thank you very much for the
following, appreciate it.
KAREEM ZIDANE: Thank you.
All right, so these are the
defaults, request headers
that Curl seems to be
sending by default.
There are a bunch of others if you
want to look at the documentation.
There are so many other requests
headers that we can use.
And the next part here is the response
that we got back from the server.
And so the first line says, HTTP/1.1.
And this is just the server
saying back that, hey, I
speak the same HTTP version.
COLTON OGDEN: So we
know they're speaking
the same language at this point.
KAREEM ZIDANE: Exactly.
COLTON OGDEN: They're both
saying essentially same thing.
KAREEM ZIDANE: Yes.
The server also adds
200 OK in this case.
And 200 is what's known
as an HTTP status code.
And it's just a numeric
code that indicates
the status of this request or response,
whether it was successful or not.
COLTON OGDEN: Everybody
in the chat, the status
code that you're most familiar
with, go ahead and plug that.
And we won't spoil it.
But I'm sure many of
the people in the chat
have seen a HTTP status
code of a particular variety
many times on the web
and have just not--
oh, actually, [? Barrack ?] said 503.
That's true.
503's fairly common.
It's not as common--
KAREEM ZIDANE: Yes.
COLTON OGDEN: --as another
very, very common one right now.
KAREEM ZIDANE: Lots of people
are mentioning it right now.
COLTON OGDEN: Yeah, let
everybody know this.
KAREEM ZIDANE: It's not a secret really.
It's 404.
COLTON OGDEN: Yeah, there we go.
404.
Someone says 401 though.
Someone's got 401 a
few times, 403 as well.
[? Barrack, ?] OK, that was sarcasm.
OK.
I've definitely seen
503 a handful of times.
But there we go, 418.
That's the troll.
I'm a teapot.
It is a real one, but it's
not a very common one.
KAREEM ZIDANE: One of them was--
I think was it that one was an
April's fool at some point I think?
COLTON OGDEN: Yup, by
the creators of a HTTP--
KAREEM ZIDANE: Yeah.
COLTON OGDEN: --or the maintainers.
And then [? Dement, ?] 301, yeah,
that's actually a redirect [INAUDIBLE]..
KAREEM ZIDANE: That's also--
COLTON OGDEN: Yeah.
KAREEM ZIDANE: --fairly
common as well, a redirect.
I think that would be
permanent redirection.
COLTON OGDEN: Yeah.
KAREEM ZIDANE: OK.
So we have a bunch of others.
People are very familiar with
different HTTP status codes here.
COLTON OGDEN: Yeah.
KAREEM ZIDANE: So I'm not
going to spend much time.
COLTON OGDEN: You're
preaching to the choir.
KAREEM ZIDANE: Yeah, exactly.
COLTON OGDEN: Everybody already knows
everything you're talking about.
[INAUDIBLE], Kareem.
KAREEM ZIDANE: Yeah, I'm not
going to [INAUDIBLE] end up.
I guess there's not
nothing to talk about.
[LAUGHTER]
OK.
COLTON OGDEN: They're actually
going to teach you Flask today.
KAREEM ZIDANE: Yeah, I
would actually be very
interesting to learn more about this.
OK.
So it says 200 OK.
Hey, your request was OK.
Here's a response.
It also sends a server response header.
And what this actually says is, hey, you
know, the kind of server that's running
is actually this weird name, ecstatic.
COLTON OGDEN: It's a very
happy, ecstatic server.
KAREEM ZIDANE: Yeah, 330.
And actually for security reasons,
some actual servers or some people
choose to configure the servers to
not send that particular header.
COLTON OGDEN: [INAUDIBLE].
Because then they know if
you have a particular version
of a particular server that
has a security vulnerability.
KAREEM ZIDANE: Exactly.
COLTON OGDEN: You've kind of
expressed that to the world.
KAREEM ZIDANE: Yeah, making
the chances higher of someone,
you know, exploiting that.
The next header here is cache control.
And this is a header that
says the server is trying
to say to the client, hey,
you can cache this response
for this many seconds, which is
3,600, which is like an hour.
So the server is
essentially saying, hey,
don't ask me about the same
thing within an hour, right?
And this can be useful, of course, to
sort of reduce traffic on our servers
if browsers can cache this data.
You know, a bunch of other
headers-- last modified.
Content length is the
actually the size of the file
that the server is sending back.
COLTON OGDEN: In bytes, correct?
KAREEM ZIDANE: In bytes, yes.
Here's the MIME type
that you talked about.
COLTON OGDEN: Right.
KAREEM ZIDANE: There's the content type
header, which includes a MIME type.
In this case, the type of data that
we're sending back is text/html.
COLTON OGDEN: Right.
KAREEM ZIDANE: There
are a bunch of others,
too, if you want to check
them out, and a couple other
headers that we won't
actually dive into,
but you're free to read more on
them or other headers online.
And following that, following
all the headers that we got,
there's actually the data,
which is the body of response.
COLTON OGDEN: The stuff that
we actually really care about.
KAREEM ZIDANE: The stuff
that we actually care about.
COLTON OGDEN: Ultimately, yeah.
KAREEM ZIDANE: So you
can imagine like this
is what actually happens when you try to
make a request through the same server
in your browser.
It sends these requests headers.
It gets back--
COLTON OGDEN: You don't
get all of that stuff.
KAREEM ZIDANE: Exactly.
COLTON OGDEN: As the end user, you see
that, but rendered in a visual format.
KAREEM ZIDANE: Exactly.
So the browser takes care of all
that, parses all the headers,
parses the body of
the response, and then
translates it into the sort of
page that you see or whatever.
COLTON OGDEN: Images
and text and whatnot--
KAREEM ZIDANE: Yeah, whatever resource.
COLTON OGDEN: --that you
end up seeing ultimately.
KAREEM ZIDANE: Exactly.
That's exactly right.
COLTON OGDEN: "Do you know
when Professor David will
do the next Livestream?"
This is [? Oncu255. ?] And then
[? In The ?] [? Ready ?] kindly said,
"he'll be on Friday on the stream for
the code review," which is correct.
We are indeed having a code review.
So anybody that's here in
the chat that's not aware,
if you go to
bitly/cs50/codereview here, we're
accepting source code on GitHub or Gist.
And if you want us to review
it on stream on Friday
with David, David and myself, definitely
go ahead and toss us your repos.
And it's going to be a
style slash design review.
It's not going to be bug
testing or anything like that.
So don't, ideally, send us broken code.
Send us working code.
And this is more catered also towards
beginner to intermediate programmers
students who want just a little
bit of help with their style,
much in the same way that we do sort
of CS50 Harvard students style grading.
Ideally, don't send us
CS50 pset repos, just so
that we don't have to spoil
solutions for students online.
But send us all of your repos that
are not CS50, ideally, pset related.
And we will take a look at it.
KAREEM ZIDANE: Yeah.
That should be so much fun.
COLTON OGDEN: Yeah, I'm excited.
We have quite a few people
that have already submitted.
And you know, if it does well, we
might do more than one episode.
But this Friday will be
our very first version
of that sort of side
series for this channel.
So I'm very excited to
take a look at that.
KAREEM ZIDANE: Cool.
All right, so I'm just quickly going
to show the same thing in the browser.
So if you visit local host,
call 8080 in the browser,
you should see if you open your
developer tools by right clicking,
and then Inspect, and then
choosing the Networks tab,
you should be able to
see different information
about the request and the response,
pretty much the same information.
Maybe Chrome includes a
couple more request headers,
a couple different values for them.
But it should be
essentially the same thing.
COLTON OGDEN: Right, OK.
KAREEM ZIDANE: And of
course, on top of that,
you get the page rendered as
you expect, which [INAUDIBLE]..
COLTON OGDEN: You get access
to all the same information,
just in a more user-friendly
way [INAUDIBLE]..
KAREEM ZIDANE: Yeah, exactly.
Cool.
All right, so now that
we've demonstrated this,
another thing that I
want to talk about is
the difference between a static
website and a dynamic website.
COLTON OGDEN: Sure.
OK.
KAREEM ZIDANE: And what do
you think a static website is?
COLTON OGDEN: A static
website to me means a website
that, if we go to that page
as many times as we want,
it's going to show us the
exact same content every time.
KAREEM ZIDANE: Exactly.
I mean, also to add to that, if you
go to that page or I go to that page,
we should technically
see the same content.
It doesn't change--
COLTON OGDEN: Correct.
KAREEM ZIDANE: --if the user changes.
And technically, some websites could
use JavaScript and some external APIs
to change their contents maybe per
user, maybe different use cases.
So we're not going to
worry about that for now.
I think they would
still be static websites
since there is no back end
that's handling something here.
COLTON OGDEN: Right.
KAREEM ZIDANE: A dynamic
website, on the other hand--
so a static website,
actually as an example,
would be the documentation for
our pset specifications, right?
So if Colton goes to
pset 0 specifications,
he will see the same thing
as I'm seeing right now.
COLTON OGDEN: Yup.
KAREEM ZIDANE: Right?
A dynamic website, on the other hand,
will be something like Facebook,
or Twitter, or Reddit,
whatever social network.
COLTON OGDEN: Yeah.
It changes every time you refresh.
You have all your friends and their
posts, all the comments, all the likes.
The like number could change.
KAREEM ZIDANE: Exactly.
COLTON OGDEN: The profile pictures
of your friends could change.
KAREEM ZIDANE: Yeah.
Different people see different things.
You know, I see my
name on the top right.
You see your name on the top right.
People who are not logged in see
completely different things and so on.
And so that's often referred
to as a dynamic website.
A dynamic website also
has a back end that's
up and running handling
different requests as we'll
have one today and demonstrate
and go through something.
All right, so let me get out
of this and start with actually
our first Flask related example.
COLTON OGDEN: [? Dmsmtp ?]
and saltyglowstick,
thank you very much for
the follows as well.
KAREEM ZIDANE: Thank you.
All right, so the first thing that
we need to have to work with this
is have Python installed.
COLTON OGDEN: Sure.
That's going to be important
if we're programming
in Python, anything in Python.
KAREEM ZIDANE: I'm not going to
provide instructions on that.
But if you go to python.org or
whatever the URL is, it should be--
COLTON OGDEN: I think it's by the node.
KAREEM ZIDANE: --there for [INAUDIBLE].
COLTON OGDEN: I'll plug it.
Everybody let me know if
that's the correct link.
And also, shout out to the regulars,
[? Nawanda, ?] [? Bella, ?]
[? Bavik, ?] [? Andre, ?]
[? Whipstreak, ?] there were multiple
other ones that we saw up above.
We have some new ones [? Oncu, ?]
[? Dement, ?] In The Ready,
which we've mentioned before,
[? mkloppenburg, ?] who left early
unfortunately, but thanks for popping,
[? Varani, ?] and then all of the other
folks I've mentioned so far.
Apologies if I did not
catch your name, but thank
you very much to all the people
that are tuning in right now
and have been tuning in so far.
KAREEM ZIDANE: All right, so I
have Python already installed.
In this case, I have Python 3.7.
I think Python 3 in general should work.
And the first thing we need to do to
install Flask is pip3 install flask,
right?
And of course, pip3 is not found,
because I need to install pip3.
COLTON OGDEN: Yup So pip3 is a
package manager for Python, right?
KAREEM ZIDANE: Correct, yes.
It's a software that allows you to
install a package, remove packages.
COLTON OGDEN: And apt-get is
kind of like that, but that's
for use for Linux.
KAREEM ZIDANE: For
Ubuntu and [INAUDIBLE]..
COLTON OGDEN: Oh, for Ubuntu Linux.
Right, because fedora could be for--
KAREEM ZIDANE: It's also in a
bunch of other distributions.
COLTON OGDEN: [INAUDIBLE] or whatever.
KAREEM ZIDANE: But Ubuntu, I
guess, is the most popular one.
So I'm right now installing
[? pip3, ?] as you can see.
COLTON OGDEN: It's a
massive installation.
KAREEM ZIDANE: Yeah.
And hopefully, that should work
this time, pip install flask.
And all good.
OK.
So we now have Flask installed.
To verify that, you can run
Flask [INAUDIBLE] version.
And it should output something.
COLTON OGDEN: Outputs an error.
KAREEM ZIDANE: OK, outputs an error.
I mean, ideally, this wouldn't
show up on your computer.
But it's actually showing me what
to do to fix this error here.
So I'm just going to follow this
instruction and try again maybe.
Hopefully, it won't break this time.
OK.
COLTON OGDEN: Nice.
KAREEM ZIDANE: So I
just needed to export
a couple of environment variables.
It's showing me what to do here.
So I did it, and it worked.
This is what you should see when
you run Flask [INAUDIBLE] version
to verify that it was
installed correctly.
COLTON OGDEN: OK.
KAREEM ZIDANE: All right,
so I'm going to dive
into the first example of the day.
And the goal of this example is to sort
of visit the same URL that we visited
a few seconds ago, a few
minutes ago, and sort of
see simply hello as a response--
COLTON OGDEN: OK, sure.
KAREEM ZIDANE: --so nothing fancy.
And the way to do that
would be, first of all,
we need to import Flask with a
capital F from flask, the lowercase.
COLTON OGDEN: Yup.
KAREEM ZIDANE: And we need to
create an app, instantiate an app.
And this app needs to be passed
some string that sort of identifies
that app.
I mean, usually at the
beginning, you shouldn't really
worry too much about this.
Most people just pass __name__.
Yup.
So don't worry about this for now.
Just instantiate the app
the way it is right now.
And the next thing that we see here
is an app.route/, forward slash.
And what do you think?
Do you know anything
about the @ in Python?
COLTON OGDEN: I know it's a decorator.
So it's kind of like a higher order
function in Python a little bit.
That's kind of a generalization for it.
Basically, [? wraps, ?]
another function,
does some information either before
or after it and returns that function,
that [? wrapped ?] function.
KAREEM ZIDANE: Correct.
So in Python, functions are what they
call first class objects I think.
COLTON OGDEN: First class objects, yeah.
KAREEM ZIDANE: Yes.
And so a function can be passed to
another function as an argument,
can be returned from another
function as an argument.
And a decorator simply
is a function that
takes another function as an argument
or takes a function as an argument
and returns a function.
COLTON OGDEN: Yup, exactly.
KAREEM ZIDANE: Right?
So if you had to guess,
what does this do
in this case, what does this
decorator do in this case?
COLTON OGDEN: Well,
in this case, it looks
like it's making whatever the function
below it does do some operation,
some logic, when they get directed to
the string that's passed into route.
KAREEM ZIDANE: Correct.
So Flask actually handles of
ton of stuff for us for free.
And as you mentioned, the way to
apply a decorator to a function
is using the @ decorator and then
pass it any arguments that it needs.
And then right after that, you should
just define your function normally.
And the way this works when this program
runs, what's actually going to happen
is that this function index is actually
going to be passed as an argument
to the decorator.
And another function is to be returned.
Presumably, that other
function has some other logic
that wraps around lots
of complicated stuff
that we hopefully don't
want to go through.
COLTON OGDEN: All the magic.
KAREEM ZIDANE: Exactly.
And part of the magic in this case
is route handling as you mentioned.
So in this case, if I receive
a request on slash, right--
COLTON OGDEN: You probably
have some global object, too,
that manages all the routing.
And then this adds that
information to that global object
or whatever could be
defined the function.
Yeah.
KAREEM ZIDANE: Yeah.
That would be my guess.
So in this case, if I receive a
request on slash, what should we do?
We should return hello.
COLTON OGDEN: Right.
And the name of the function
itself doesn't really matter.
Because all Flask is
really doing, I'm guessing,
internally is keeping a
reference to those function names
and managing that on its own.
KAREEM ZIDANE: Correct.
COLTON OGDEN: It's saying, if the
user goes to slash, call index, right?
KAREEM ZIDANE: Correct.
COLTON OGDEN: Because
it's mapping it probably
just having a direct
reference to the function.
Because, like you
said, it's first class.
So it just really needs to refer
to its symbol, and it can call it.
KAREEM ZIDANE: I can't remember exactly,
but I believe the name of the function
only matters if you use the
URL underscore 4 functionality.
COLTON OGDEN: I think yeah.
I think so yeah.
KAREEM ZIDANE: We're not
going to be using that today.
But just for now for simplicity,
this name can be anything you want.
It can be foo.
It can be bar.
It can be anything you want.
What actually matters is the
decorator that's before it.
COLTON OGDEN: Correct.
KAREEM ZIDANE: If you have
a route [? on ?] slash,
the following function is going to
be run when you visit that route.
COLTON OGDEN: Let's answer a
couple of questions from the chat.
So [INAUDIBLE] says, "why does mail
from the SMTP library go into spam?"
Do you happen to know offhand?
KAREEM ZIDANE: I mean, I don't
really know much about this.
But usually sort of mail
servers have some ways
of verifying whether the party that has
sent this email is actually legitimate
or not.
COLTON OGDEN: Sure.
KAREEM ZIDANE: Like, for example, if you
use your own web server, your own mail
server, to send people some
emails, other mail servers
upon receiving this email don't
really know who this server belongs to
or whether it's malicious or not.
So they usually filter
it as spam by default.
COLTON OGDEN: Make sense.
I can imagine that
happening, too, if you
say that I'm sending email
from some messages not
actually what the from sender is.
You know, if you say I'm sending
this from coltonoscopy@gmail.com,
which is my email address, but my Flask
server isn't going from gmail.com,
it's coming from some
random server somewhere--
KAREEM ZIDANE: Exactly.
COLTON OGDEN: --that's
probably an indicator
to Gmail or some other service
that this is probably illegitimate.
KAREEM ZIDANE: Yeah.
As you mentioned, you can
spoof email addresses,
the phony email addresses,
and make it seem
like someone else is sending an email.
But, you know, again,
some web servers do
have ways to handle this
whether by filtering it as spam
or showing you some icon that says
this might be a malicious email.
But, yeah, this should be possible.
COLTON OGDEN: [? Dement0 ?] says,
"first time joining your Livestream.
The earlier ones you
did-- watched on YouTube.
This time decided to join the steam
to say hi, Colton and Kareem."
KAREEM ZIDANE: All right, hi there.
COLTON OGDEN: Awesome.
Thank you so much, [? Dement, ?]
really appreciate it.
Thanks for tuning in live,
really appreciate it.
[? Andre's ?] clarifying about the
Debian Linux package manager apt-get
in Ubuntu and other [INAUDIBLE] use it.
[? Varani ?] says, "this looks
very similar to Express.js."
It's been a little while since
I've used express actually.
But I mean a lot of these sort of
micro-- these frameworks, back end
frameworks kind of look similar.
The routing kind of looks very similar.
KAREEM ZIDANE: Yeah.
COLTON OGDEN: It's a common paradigm.
And Laravel, I think, for its PHP
framework, adopts a similar convention.
KAREEM ZIDANE: Correct.
COLTON OGDEN: "Which course do
Harvard students do after CS50?"
Generally, CS51 is the next go to.
And that's that kind of an
object-oriented functional programming
course.
And there's operating systems,
and algorithms, data structures.
A discrete math course that you
took, the extension version of it,
students will take something like that.
Which course?
What number was that?
Do you remember?
KAREEM ZIDANE: The discrete math course?
COLTON OGDEN: Yeah.
KAREEM ZIDANE: I think
it was CS20 or something.
COLTON OGDEN: Oh.
Yeah, yeah.
CS20.
So yeah.
KAREEM ZIDANE: Yeah.
COLTON OGDEN: It doesn't necessarily
go higher number than CS50, but, yeah,
there's a bunch, whole
bunch of different ones.
"All the CS50 team is
doing an amazing job
to make these technologies easy to
learn and follow thank you very much.
Please keep doing what you do."
Hey, that's a nice compliment.
KAREEM ZIDANE: Yeah, thank you.
COLTON OGDEN: Thank you very much,
[? Dement, ?] really appreciate it.
"I also need a CS50 hoodie and
T-shirt," says [INAUDIBLE]..
Yeah, well, if you teach CS50, you
can have one of these awesome hoodies.
But you got it to become a staff member.
KAREEM ZIDANE: Yeah.
COLTON OGDEN: "It's a
dream learning from CS50."
Also, protip, when
spoofing an email, make
sure you're not
auto-appending your signature.
Probably.
KAREEM ZIDANE: OK.
COLTON OGDEN: That's probably
something you don't want to do.
KAREEM ZIDANE: All right, so let's
actually test this in action.
So the way to run this
would be by navigating
to the folder where your [INAUDIBLE]
in this case and then run Flask run,
and then optionally, -p, and then the
port number that you want to listen on.
COLTON OGDEN: OK.
KAREEM ZIDANE: By default,
Flask listens on port 5,000.
I prefer using 8080.
There's no real difference
here except that I
have this exposed from my container.
So I'm just going to
listen on port 8080.
And when you do this, Flask
has a built-in server.
It's actually from another framework.
But it has a server that starts up
and starts expecting information
on this particular port.
I think this is going to fail.
Let me see why.
COLTON OGDEN: Very optimistic of you.
KAREEM ZIDANE: Yeah.
I mean, I noticed
something that I need to--
OK.
Well, is that correct?
Did we expect that?
COLTON OGDEN: Oh,
because that says hello.
KAREEM ZIDANE: Yeah.
COLTON OGDEN: And the message said,
hello there in the web browser.
KAREEM ZIDANE: It might
be listening on some--
there has to be another server
that's listening on this.
Let's see.
OK.
That's weird.
COLTON OGDEN: Well, weren't
you just using the HTTP server
in your Docker container?
KAREEM ZIDANE: OK.
Now, it works as expected.
COLTON OGDEN: Oh, was a caching it?
KAREEM ZIDANE: I think
it was caching it, yes.
COLTON OGDEN: Oh, OK.
Interesting.
KAREEM ZIDANE: All right,
so this doesn't work,
because I'm listening
on IP address 127.0.0.1.
And I'm inside the container.
So it's a little bit confusing.
For my host, 127.0.0.1 is the
host itself, not the container.
COLTON OGDEN: Right.
KAREEM ZIDANE: So what I want to do is
listen for actually all IP addresses
inside of this container.
Again, if you're running
this on your host
directly, if you're not using
Docker, don't worry about this.
You shouldn't need this argument.
But I'm going to do this for now.
And I get what I expect
to get, which is hello.
COLTON OGDEN: Nice, OK.
KAREEM ZIDANE: All right,
so very simple, very easy.
Let's switch to the second
example that we have today.
And this example would
essentially expect
some piece of data that can be
different from request to request.
And then it returns a response that's
different based on that piece of data.
COLTON OGDEN: OK.
KAREEM ZIDANE: So in this case,
I'm expecting a name get parameter.
As we mentioned earlier, we can send
get requests, we can post requests.
And we can parametrize
these requests in the sense
that we can include variables or
parameters with different values
each time.
COLTON OGDEN: Right.
KAREEM ZIDANE: Right?
So in this case, I'm expecting a
parameter called name with a name name,
literally, and with a value presumably
the name of the person who's
making the request.
COLTON OGDEN: OK.
KAREEM ZIDANE: Right?
So the way to make a request with a
get parameter like this would be as
follows.
Let's just make sure the
server's running first.
So let's run the server
on the same port.
And now the way to do this
would be to append a question
mark to the end of your URL and then
mention the name of the variable
or the name of your
parameter equals its value.
So in this case, I'm
going to say my name.
COLTON OGDEN: The key value pairs?
KAREEM ZIDANE: Exactly.
So name of the parameter equals
the value of the parameter, right?
COLTON OGDEN: OK.
KAREEM ZIDANE: And hit Enter.
And I get hello, Kareem.
COLTON OGDEN: Nice,
works very splendidly.
So if you did name equals nothing?
KAREEM ZIDANE: [? Correct. ?]
Well, that's a good point.
If I don't include this parameter
at all, that's a little buggy.
COLTON OGDEN: Hello, [? none. ?] Nice.
KAREEM ZIDANE: Right?
COLTON OGDEN: OK.
KAREEM ZIDANE: And that's because
the default value of this parameter
is none.
COLTON OGDEN: Right.
KAREEM ZIDANE: Or the default
value that's requested
are-- so get returns here is
actually not for this parameter.
COLTON OGDEN: What if you did
hello equals, and then nothing
after the equals?
KAREEM ZIDANE: I think it
would be the same thing.
Would it be an empty string?
COLTON OGDEN: Let's try it.
KAREEM ZIDANE: It would be
an empty string I think.
COLTON OGDEN: Let's try it.
KAREEM ZIDANE: So let me actually
get this running somewhere else.
COLTON OGDEN: And, also, thank you very
much to [INAUDIBLE] and [INAUDIBLE]..
I apologize if I butchered that.
Thank you both very much for following.
8880.
all right, let me see.
Oh, I have to be in the same shell.
OK.
All right, I didn't think about
this before this [? seam. ?]
But, anyway, if we did name equals
this, it's going to be [INAUDIBLE]..
COLTON OGDEN: Nice.
OK, so a different behavior.
OK.
KAREEM ZIDANE: Right?
So this is a different
value technically.
COLTON OGDEN: Yeah.
KAREEM ZIDANE: In the first case, in
the case where the name is not present
at all, the parameter
is not present at all.
And so the default value that
get returns here is none.
COLTON OGDEN: Correct.
KAREEM ZIDANE: But in this case,
actually the parameter is present.
And there is a value for it.
And this value is empty, right?
So it just returns the empty string
COLTON OGDEN: Nice.
KAREEM ZIDANE: Right?
COLTON OGDEN: OK.
KAREEM ZIDANE: So there are
ways where we can handle this.
We're not going to worry too
much about this right now.
The second thing that I
wanted to mention about this
is that if I have more than one
parameter, more than one key value
pairs, they are separated
with an ampersand.
So if I have name equals Colton and
email equals colton@cs50.harvard.edu,
this is how this would be read.
COLTON OGDEN: Right, OK.
KAREEM ZIDANE: That's [INAUDIBLE].
COLTON OGDEN: And then you
could get more than one variable
inside your route just by grabbing the
request.args.get email in this case.
KAREEM ZIDANE: Correct.
Yeah.
So this is the way that we get
the value of a get parameter
called name, request.args.get name.
And notice that we have to import
request from Flask up here as well.
COLTON OGDEN: Nice.
OK.
We have a couple questions
in the chat, too.
KAREEM ZIDANE: OK.
COLTON OGDEN: [? Webstreak ?]
is asking, "quick question,
does there happen to be message input
into the rendered template function,"
which you haven't gotten to yet.
KAREEM ZIDANE: We haven't
gone to that part yet.
I don't know off the top of my head.
I don't think I've used it before.
But let's actually
check the documentation.
Let's see.
So there is the render
template function.
I don't see a message parameter here.
So I don't think it has one.
COLTON OGDEN: Yeah.
And I think in this case wouldn't
you just pass in whatever variables
you want and then have the templating
thing sort of take care of?
KAREEM ZIDANE: Yeah.
COLTON OGDEN: And there's
also flash messaging, which
I think you can integrate
into Jinja, can't you?
KAREEM ZIDANE: We're actually going
to demonstrate both of these today.
COLTON OGDEN: OK.
KAREEM ZIDANE: We're going to
demonstrate passing data to a template
and then flashing some messages.
COLTON OGDEN: OK.
KAREEM ZIDANE: So if
you're curious, stay tuned.
COLTON OGDEN: Cool, cool.
Next question, "how would you
pass data from the client side,
e.g. a JPEG image, to Python Flask
server and then return results?"
KAREEM ZIDANE: OK.
That's a different way of doing it.
Usually, when the data
is binary like this,
it's the case that we
make a POST request which
is the same kind of request
that we're going to talk about.
And essentially, the data
of this image or whatever
file you're trying to upload is sort
of encoded as part of the request
when the browser makes
that POST request.
We're not going to demonstrate
uploading files today.
But it wouldn't be a part of the URL as
is the case with get parameters here.
COLTON OGDEN: OK.
KAREEM ZIDANE: Right?
It wouldn't be [INAUDIBLE].
COLTON OGDEN: Yeah, because that's part
of the query stream, the get stuff.
And that's also stuff that
you can't really put into--
I mean, you can binary
encode information
and put that into a UTF encode
information and put that into the URL.
But that's not typically how
you see especially large data.
It's usually done through POST requests.
KAREEM ZIDANE: Yeah, I think
URLs also have a maximum length.
COLTON OGDEN: Yeah, I would imagine.
Yeah.
KAREEM ZIDANE: So if
you have a file that's
big enough, though,
even if you encoded it,
it would be a problem to
send as part of the URL.
POST requests might
be handy in this case.
COLTON OGDEN: "Can we override
routes," says [? Bavik ?] [? Knight. ?]
KAREEM ZIDANE: Can we overwrite routes?
In which sense?
We can have multiple routes.
I don't think we can have different
functions for the same route,
because at this point that would be
confusing for Flask, which function do
you want to run in this case.
So I can't have another function
with the same route here.
COLTON OGDEN: And if
you did, I would imagine
it'd be the bottom one that would
take over, that would take precedence.
KAREEM ZIDANE: It could be.
Because it would
overriding it in this case.
But in this case, it would be
useless to have the first function
[? in the first place. ?]
COLTON OGDEN: It would.
It would.
It would.
[? Frame ?] [? of ?] [? Ref ?]
says, "just to clarify,
is the request library
part of Python or Flask?"
KAREEM ZIDANE: Yes, the request
module is part of Flask in this case.
It's not a different, not a
separate library or anything.
I just installed Flask up to this point.
All right, and the last
thing that I wanted
to mention before leaving this
example is this notion over here.
And this is actually part of the Python
3.6 syntax, which is a format string.
Notice, we have an F here, right?
And then this is the way I'm sort
of injecting the value of the name
variable into my response.
COLTON OGDEN: The format string, one
of my favorite Python 3.6 features.
KAREEM ZIDANE: Yeah, indeed.
COLTON OGDEN: Probably
my favorite 3.6 feature.
I don't remember what else 3.6 added
that I thought was really great.
KAREEM ZIDANE: It's really quite handy.
We're going to see a fairly similar
syntax when we go into templating,
which I think starts the next example.
COLTON OGDEN: Yeah.
KAREEM ZIDANE: Right.
Do we have any more questions so far?
COLTON OGDEN: We do.
So [? NACL ?] [? Eric ?] is asking,
"is it possible to make an HTTP request
from a GUI, like Postman, if your app
is being hosted on a Docker container?"
KAREEM ZIDANE: Yes.
And we're not going to dive into details
about how Docker works in this case.
But, essentially, you can map ports
from the Docker container into the host.
And it would be like the
client wouldn't really care
where the app is hosted in this case.
COLTON OGDEN: As far as where it
could be a server somewhere else?
KAREEM ZIDANE: Yeah, exactly.
COLTON OGDEN: Just a virtual server?
KAREEM ZIDANE: Exactly.
COLTON OGDEN: And then
[? Aldu ?] is asking, "is there
a schedule somewhere
of what you are going
to cover in the upcoming streams?"
We keep all of them as Facebook Events.
But, yeah, in the near
future, we are going
to start integrating I think
a schedule into Twitch itself.
But you can go to facebook.com/cs50.
And that's where we post all the
events for all of our upcoming streams.
We also post them to our
Reddit and our Twitter account,
facebook.com/cs50 and then
reddit.com/r/cs50 if I'm not mistaken--
yeah, /r/cs50-- and then twitter.com/--
whoops.
There we go.
twitter.com/cs50, let me make
sure that that is indeed accurate.
But the simplest way to do it is just to
go to Facebook for now, facebook.com--
I can't type-- /cs50.
All of our [INAUDIBLE] are there.
All right, cool.
KAREEM ZIDANE: All right, that's great.
So the next example that we're going
to dive into involves some templating.
Flask, by default, has as part of
it a templating engine called Jinja.
And we're going to explore a little
bit of the syntax for Jinja today.
So this following example is
a little bit more complicated
than the previous one.
The first thing that we have here
is our routes on slash that's
handled by rendering a template
apparently called index.html.
COLTON OGDEN: And this is what
Nate was referring to, Nate
being [? whipstreet23 ?] when
he asked about render template
taking a message parameter.
KAREEM ZIDANE: Correct.
COLTON OGDEN: In this
case, rendered template
looks like a URL or an
actual HTML page that we
might have they we want to
serve people, but also takes
in some other information.
KAREEM ZIDANE: Yeah.
And let we actually clarify why
templating would be useful in this case
or in general.
So if you have a website of some
sort and you have a bunch of pages,
every HTML page ideally should start
by-- let's open a sample one here.
It should start by something
like doc type, html, you know,
whoops, html, and then html closing tag.
And then we have a head.
And you'll have a body.
And you'll have a bunch of other things
inside of the head maybe and so on.
And so it'd be really boring to sort
of keep copying and pasting this
into every page that you have.
Another thing is that if you
want to change something,
if you want to add a
script or if you want
to add a link, a CSS somewhere,
or rather in all of them,
you'd have to copy and paste that
into every page that you have.
And so templating sort
of solves this problem
by essentially allowing
you to have one base
file that you sort of inherit from
and sort of plug in certain parts
as we'll see.
COLTON OGDEN: It's kind of a
common paradigm in, I think,
software development in general--
KAREEM ZIDANE: Correct.
COLTON OGDEN: --composable
parts, inheritance,
like these sort of concepts I think.
We even use this in the
game streams, for example.
KAREEM ZIDANE: Yes.
COLTON OGDEN: State
machines, we did that
with state machine
example with a base state
that other states can inherit from
to get functions that they don't
have to override themselves, right?
They just copy the
functions from other states.
KAREEM ZIDANE: Yeah.
I mean, inheritance in the context
of object-oriented programming
is a little bit different here.
Because you can think of it the same
way that you think of a pre-processor,
a C preprocessor.
It just literally, you know, pastes
your stuff from the base file
and then plugs into the
stuff that's [INAUDIBLE]..
COLTON OGDEN: Yeah, definitely a
simpler implementation here, but yeah.
KAREEM ZIDANE: All right,
so by default, Flask
expects all of our templates to
be inside of the templates folder.
So I'm going to go into that folder.
And I'm going to open the
base HTML file that I have.
And it looks like this.
It's called the layout.html.
And it looks like this, has all the
parts that we need for any HTML file
in general, the doc type, the HTML,
the head, the body, and so on.
And it also has this sort of
curly brace curly brace notation.
And this is actually a
Jinja specific syntax.
This actually says, you know, if
there is a keyword argument passed
into render a template
whose name is title,
replace its value here,
or plug in its value here.
And so let me go back up here.
And I'm not sure if that's--
can I make this a little bit
smaller, so that we can see?
Maybe put it up?
COLTON OGDEN: Oh, yeah.
We can probably mess with the
chat and make it a little smaller.
KAREEM ZIDANE: Yeah.
COLTON OGDEN: We can do that.
Whoa.
Hey, there.
KAREEM ZIDANE: All right.
COLTON OGDEN: It's just briefly,
make it small just briefly.
KAREEM ZIDANE: So in the render
template call here that I called,
I passed in a keyword
argument called title.
And I passed in the value
Homepage in this case.
COLTON OGDEN: Right.
KAREEM ZIDANE: So this
essentially says that, hey,
if there is a keyword
argument called title
passed to render template, replace
its value here, or plug in its value
at this very same location.
And this location happens to be
the title of our page in its case.
COLTON OGDEN: So this is like the
precursor to really getting us
into a more dynamic sort of web content.
KAREEM ZIDANE: Correct.
Yes.
And so as you can imagine, different
calls to render a template,
as you mentioned, can receive different
values for the title parameter.
COLTON OGDEN: Even if it takes in a
name, hello Kareem versus hello Colton,
that's technically a dynamic webpage.
KAREEM ZIDANE: Correct.
COLTON OGDEN: To answer a couple
questions in the chat, too, also--
[? Giban3 ?] said, "I used to
do the same thing with PHP,
making a header and footer and
then having the PHP call it in."
Yeah, that's kind of
what we're doing here.
KAREEM ZIDANE: [INAUDIBLE]
COLTON OGDEN: Well, I mean, it's
an idea of what we're doing.
Because it's sort of what we're leading
to, right, having a header and a footer
that we can inherit from template?
KAREEM ZIDANE: Oh, yeah.
Yeah, yeah.
COLTON OGDEN: Yeah.
KAREEM ZIDANE: Yeah.
COLTON OGDEN: [INAUDIBLE]
KAREEM ZIDANE: Yeah, you can
pretty much do that as well.
COLTON OGDEN: And then [? Andre ?]
was saying, "templating
is closer to generic programming."
So templating in C++ is not the same
thing as templating templates in Jinja
or Flask.
In this case, these are just kind
of like pre-created documents
that we inject variables into.
Templating in Java or-- it's called
generics in Java-- templating in C++,
those are functions that can take very
adic arguments of different types.
And they get compiled
into multiple different--
how do I want to describe this?
They get compiled into multiple
versions of the same function that
can take multiple data types.
And this is done at compile time.
And then template meta
programming is related to that,
that same thing in C++ where
you can, at compile time,
basically generate a compute table or a
lookup table for a series of functions
and their outputs, and then get
insane performance boost that way,
especially in games programming
where you're calling a function maybe
hundreds of times or rather not
hundreds of times a second--
well, I guess hundreds
of the times a second.
No, I guess you couldn't be doing
hundreds of times in a second.
Hundreds of times in a loop maybe
over the course of a couple of frames
or whatever, this is kind of
where you'd use templating.
But it's, yeah, completely
separate I think from this domain,
but the same name templating.
Not--
KAREEM ZIDANE: Can be [INAUDIBLE].
COLTON OGDEN: --synonymous, but very,
very different use cases, same word.
And [? Belacures ?] is asking, "if we
don't mention any methods in the route,
will Flask answer only
to a get request?"
KAREEM ZIDANE: That is correct.
And we're going to explore the methods
parameter to the decorator here.
But, yeah, if I just say app.routes/,
this is expecting only get requests.
COLTON OGDEN: OK.
KAREEM ZIDANE: And so
what this means, if I
try to send another kind of
request or if the browser tries
to send another kind
of request, the server
is going to hopefully
respond with some error code.
In this case, I think it's 405,
method not allowed or something.
COLTON OGDEN: Makes sense.
And lastly, [? Adam ?]
[? Fighter ?] says,
"templates in Jinja2 are like
Python format strings on steroids."
KAREEM ZIDANE: Yes, kind of.
They're a little bit fancy, a
little bit more complicated,
because they involve some sort
of logic in them that we'll see.
COLTON OGDEN: True.
KAREEM ZIDANE: But the idea is
the same, that you have some base.
And then it has some variables
that you can sort of plug into,
and it just becomes different.
All right, the next interesting
piece here, or snippet I should say,
is the block some word end block in that
very same syntax, so curly brace, %,
block, name, %, and so on.
And so what this does is
actually says that, hey,
the templates that are going to
extend or inherit from this base
can essentially define a block.
And the contents of this block
are going to be inserted here.
So let's actually take a look
at one of these templates.
So let's take a look at index.html.
And the first line in index.html
is that it extends layout.html,
the file that we just looked at.
COLTON OGDEN: OK.
KAREEM ZIDANE: Right?
COLTON OGDEN: So it's going
to inject the body block sort
of into that-- layout.html
is kind like a template
that we're saying, we're
going to put our own block,
our own custom block, into this
place holder for a block, right?
So in this case, block body
and then the actual layout
defines body and then gets
injected into it, right?
KAREEM ZIDANE: Yup, exactly.
COLTON OGDEN: Or index.html.
KAREEM ZIDANE: In this case,
everything from layout.html
is going to be included in index.html.
And the place where
this line over here is
going to be replaced with
the contents of this--
COLTON OGDEN: Sure.
KAREEM ZIDANE: --which
is this line over there.
COLTON OGDEN: It's pretty cool.
We don't have to write all the
HTML head, title, all that stuff--
KAREEM ZIDANE: Nope.
COLTON OGDEN: --in index.html.
We're only literally just writing
what the body is that we care about.
KAREEM ZIDANE: Yeah.
And that's the beauty of templating.
It makes this stuff really easy.
COLTON OGDEN: "Completely
unrelated," says
[? Webstreak, ?] "how do you
check if a text box in HTML
is empty using JavaScript?"
I pulled it up here, because
I didn't recall offhand.
But it looks like with
JavaScript you can do it
pretty easily just by checking
if an element's value dot
length is equal to zero.
to see exactly.
Oh, would it be document.get element
by ID and then the input or whatever?
I'm trying to find an
actual robust thing here.
Yeah.
KAREEM ZIDANE: Definitely do
google this stuff, though.
It can be really handy when you
run into a question like this.
Don't block yourself.
COLTON OGDEN: Yeah.
Yeah.
Like what I did was I typed into Google.
I just basically typed in
"check text box html empty."
And using something like document.get
element by ID or using jQuery.
You might have seen the $ library using
whatever selector for your text box.
So if you get an ID of text
box, you can check it by the ID
by passing in the string
with a hash symbol.
And then you can basically
check to see if value dot length
on that is equal to zero.
And that will mean that it has no
characters typed into it, in which case
it's empty.
KAREEM ZIDANE: All right.
OK.
So let's actually take a
look at how this looks.
So let me run my server again.
It's Flask, right?
Flask, OK.
So let me reload this page.
And this is what I see.
And just to be clear,
let's get back to--
what is it--
Flask stream bash.
And let me go into Flask stream.
I think we're an app2.
So this is what I have in my
template at the bottom here, right?
This is not really interesting.
So let's-- yeah.
OK.
So this is what I have here, same thing.
All right, so the idea of this--
COLTON OGDEN: Very
sophisticated, by the way.
KAREEM ZIDANE: Yeah, thanks.
The idea of this simple
web app is that it should
allow us to sort of register users.
COLTON OGDEN: OK.
KAREEM ZIDANE: Right?
Ideally, databases are used for this.
We're not going to use a database today.
Maybe in a future stream we
can talk more about database.
COLTON OGDEN: Sure.
KAREEM ZIDANE: I believe David
had a SQL streams sometimes?
COLTON OGDEN: Yeah.
We had like a SQL basics
kind of stream where we just
kind of talked about the syntax.
And SQLite, I believe, is what we used.
But doing something like Mongo or MySQL
in the future would be pretty cool.
KAREEM ZIDANE: Yeah.
So in this case today, we're not really
going to dive into any database stuff
just to make it simple.
And what we're going to
use instead is a CSV file.
And a CSV file is essentially a simple
text file with comma separated values.
So I can have a file called
users.csv in this case.
I can say that, hey, the first
column is going to be the user name.
The second column is
going to be the password.
And so I can have something
like your username.
Is that correct?
Is that correct?
COLTON OGDEN: Yeah, cogden.
Yeah.
KAREEM ZIDANE: OK.
All right?
And then your password is 123.
COLTON OGDEN: Yup.
My real password, too.
KAREEM ZIDANE: Yes.
COLTON OGDEN: There you go.
You got it.
KAREEM ZIDANE: And
then another user name,
and then another password, and so on.
COLTON OGDEN: Oh, you and
I use the same password.
KAREEM ZIDANE: Yeah.
That's a coincidence.
COLTON OGDEN: It's
probably not very secure.
KAREEM ZIDANE: I should try
this on your account sometime.
All right, so the idea of
registration in this case
is that it would take
some data from the user,
and then it would essentially insert
a row or a line into this Text file
in this very same format.
COLTON OGDEN: Yup.
KAREEM ZIDANE: Right?
COLTON OGDEN: Using a
very simple database.
KAREEM ZIDANE: Yes, correct.
So let's actually look at
this page here, Register.
And in this page, it's another
template called Register.
And it has this very similar
structure to the index.html page.
It also extends layout.html.
It also fills in the
body block in this case.
But this time, it fills
it up with a form that's
going to be submitted to register.
And I believe you talked about this
in your HTML stream, video forms?
COLTON OGDEN: We talked
about it very briefly.
That was actually the last part
before we kind of had to cut it short.
KAREEM ZIDANE: Cool.
COLTON OGDEN: We didn't really
get into the nitty-gritty of it,
but we talked about kind of like
username, password, and then buttons
and stuff like that.
KAREEM ZIDANE: So, yeah.
COLTON OGDEN: We really get into details
of like POST and GET and all that.
KAREEM ZIDANE: Essentially,
we have a form here.
And this form is going to
be submitted to /register.
And we're going to take a
look at this code after this.
This form is actually going to be
submitted using the POST request
method as opposed to GET.
COLTON OGDEN: Yup.
Completely different, right?
KAREEM ZIDANE: Right.
So, again, the main difference between
including HTTP parameters or variables
in a GET request versus
a POST request is
that, when you include HTTP
parameters in a GET request,
they appear as part of the URL.
COLTON OGDEN: Right.
KAREEM ZIDANE: But when you
do that using a POST request,
they're actually encoded as
part of the request [INAUDIBLE]..
COLTON OGDEN: So you probably don't
want to put your password as a Get,
you know?
KAREEM ZIDANE: Correct.
So form submissions,
usually, that includes things
like user names, and
passwords, and files,
and other stuff are not
typically submitted using GET.
COLTON OGDEN: Right.
KAREEM ZIDANE: They're
submitted using POST.
But what's a common form that
submitted using a GET request?
COLTON OGDEN: A common form?
I guess it would be, yeah,
like a search I guess.
KAREEM ZIDANE: Yeah.
So Google, for example, this essentially
is a form with one text field
and, you know, a couple
of buttons or whatever.
And I can search for cats.
And if we ignore all the
stuff-- actually, you know what?
Let's redo this.
So I bet if you look at this whole
URL, you're eventually going to find
something like q=cats.
And it shows the same thing essentially.
COLTON OGDEN: Right.
KAREEM ZIDANE: Right?
So this is a form that's
submitted using a GET request.
COLTON OGDEN: GET request, right.
Because we're not sort
of including any really
personal identifying information--
KAREEM ZIDANE: Correct.
COLTON OGDEN: --that
we need to keep secret.
It's kind of all--
KAREEM ZIDANE: Exactly.
And it's not just--
well, I guess it is the same thing.
It is mainly because of the secrecy.
But, also, I don't really
want to clutter my history
with all this different values of some
sort of files that I have uploaded.
Or, you know, I don't want to record my
password to be in history permanently.
COLTON OGDEN: Right.
KAREEM ZIDANE: So that's
kind of a bad thing to do.
COLTON OGDEN: To [? Andre's ?]
point, yeah, I mean,
templating in this sense and templating
and C++ are slightly similar in that
there's some plug and play of
things, like injection of, I guess--
in case the templates, you're placing
some place holder with actual data.
And you're doing the same
thing with templates in C++.
But in C++, you're doing it across
multiple different potential use cases.
And you're sort of creating
a table of multiple things,
whereas in Jinja you're
just injecting it once,
and then processing it, and then
returning that one result, right?
The purpose of sort
of generic programming
is to make it possible and more flexible
to program with certain data types.
And in templating, it's
to basically save you
from rewriting the same thing over
and over again and to kind of just
make whatever parts you want
dynamic easy to change, right?
[? Adam ?] [? Fighter's ?] asking, "can
you talk a bit about AJAX async calls
with Flask-- for example, typing a name
into a text box and having it print
instantly without refreshing the page?"
KAREEM ZIDANE: I don't think we're
going to cover this today unfortunately.
But AJAX will be an interesting thing
to discuss on a future stream as well.
COLTON OGDEN: Yeah.
KAREEM ZIDANE: But the idea is
that if you have a back end written
in Flask or whatever, as we saw
in the first couple of examples,
we can return essentially
any kind of data.
So we happen to have returned a string.
But you return a string
that's formatted as JSON
and then parse this on the
JavaScript side of things,
and then use it as a JavaScript object.
And this is how, you know, we can
dive deep into REST APIs and such.
COLTON OGDEN: Yeah.
You'd need a REST API to be able to
authenticate, get the information back
from the server, and
update the page unless you
wanted to do it in pure JavaScript.
But you still need the authentication
to know that that user is actually
a legitimate user and not just some
random person typing their username.
It's a fairly complicated.
But, yeah, I think--
KAREEM ZIDANE: If we
do have enough time,
we can demonstrate a quick
example on how that works.
But I don't have it in the
examples that I have pre-prepared.
COLTON OGDEN: [? In ?]
[? The ?] [? Ready ?] asked,
"what's the difference between
request.form name and request.form.get
name?
KAREEM ZIDANE: request.form
name and request.form.get name?
I mean, my guess--
I have to look at a
documentation for this.
I'm not sure if the parameters will
be available on the request objects
right away, like directly.
I'm not sure if you would be
able to access them this way.
But if you are, it could
be the case that GET
allows you to specify this sort
of default value, for example.
So I have to look at the documentation
for this one and see if that's accurate
or not.
COLTON OGDEN: "Can we do
functionality for the password?
Like when we try sudo, we can see only
one bullet, so someone looking over
can't guess the length of the password?"
Like limit the number of characters
that the password field reveals to us?
KAREEM ZIDANE: Definitely, yes.
I believe you can do this using
a script maybe or using maybe
something built-in
attributes into HTML if there
is such an attribute that exists.
COLTON OGDEN: Yeah, there probably is.
I haven't actually looked
into it, but I would
google "password limit
number of characters, limit
number of visible bullets" or whatever.
And there's probably a ton
of stack overflow snippets
that you could copy and paste.
Cool.
KAREEM ZIDANE: All right, so
do you have any more questions?
COLTON OGDEN: No.
I think we're all caught up.
KAREEM ZIDANE: OK, cool.
So this form, as you see here--
let's get rid of this--
has two text fields essentially.
One of them is a plain text field
and one of them a password field.
And a Submit button, these
are what I have here.
And the idea is that when I submit this
form the data from this form is going
to be submitted to the
/register route as we see here.
And the parameter names
in this case are going
to correspond to the
input element names here.
So I'm going to have ideally a parameter
called user name and a parameter
called password here.
All right, so let's
actually try this out.
So right now, let's actually verify
that the file that I have is empty.
It's completely empty,
doesn't have any data in it.
So if this works as expected, I'm going
to sign up myself with some password.
COLTON OGDEN: Probably not 1234.
KAREEM ZIDANE: Exactly.
And this is, of course,
an internal server error.
COLTON OGDEN: Oh, man,
internal server error.
KAREEM ZIDANE: Because something--
OK.
User name zero is out of range.
So let's look back in the code.
And do some live debugging.
It's really hard to see--
COLTON OGDEN: Oh, man.
It's my favorite kind of debugging.
KAREEM ZIDANE: Yeah.
You know what?
Let me do this.
Let me make this vertical so that
I can see it better hopefully.
Flask stream bash, and then we're
going to do some live debugging here,
so pardon us.
OK, app2.
COLTON OGDEN: Some live
debugging, AKA, stack overflow.
KAREEM ZIDANE: Yeah.
[INAUDIBLE]
And what was the error on line 33?
COLTON OGDEN: The list index out of
range, row zero is equal to user name.
So line 33, yeah.
KAREEM ZIDANE: Oh, interesting.
OK.
I know why this is happening.
I think, because I [? truncated ?]
the file the wrong way.
So the file is technically not empty.
The file that we saw right here
technically has a blank line.
COLTON OGDEN: Right.
KAREEM ZIDANE: Right?
COLTON OGDEN: But it's not going
to have rows that you can parse.
KAREEM ZIDANE: Exactly.
And so I think one way you can
get around this is by doing this.
So, now, it's empty.
COLTON OGDEN: OK.
KAREEM ZIDANE: Right?
So let's try this again.
Let me go back to Register.
Let me do this again.
OK.
That worked.
COLTON OGDEN: Nice, cool.
KAREEM ZIDANE: It doesn't
show anything useful.
It shows me the Index page again.
COLTON OGDEN: Right, yeah.
KAREEM ZIDANE: But let's
check the file one more time.
Whoops, users--
COLTON OGDEN: Oh.
Nice.
KAREEM ZIDANE: There's my [INAUDIBLE].
There's my password.
COLTON OGDEN: Spoiler
alert, password 123.
KAREEM ZIDANE: Exactly.
That's something you
should never do, actually.
Never store passwords
in plain text like this.
COLTON OGDEN: Yeah, encrypt them.
Yeah.
KAREEM ZIDANE: Exactly.
They are usually sort of encrypted,
as you mentioned, or hashed,
and then stored as a hash.
So that if anyone gets access
to this file or your database,
ideally, they wouldn't know what this
password is actually in plain text.
But for simplicity today, we're not
really going to talk about hashing.
We're just going to store
it has a plain password.
And let's actually verify that this
works by registering another user.
And let's say, you know, [? Aaron, ?]
for example, in this case and some
password.
And then, you know, verify this again.
We have [INAUDIBLE].
COLTON OGDEN: Much more secure
password than your password.
KAREEM ZIDANE: Correct.
COLTON OGDEN: It's still pretty
easy to brute force though.
KAREEM ZIDANE: Correct.
All right-- so kind of interesting.
What can we do with this, though?
Like, what can we do next?
COLTON OGDEN: Oh, man.
Could go a whole kinds
of different directions.
KAREEM ZIDANE: Exactly.
So, now, I'm keeping
track of some user data.
I should ideally allow them to log
in or, you know, hopefully show them
that they are logged in or not.
And that's what we're going to do next.
And so let me go into it app3.
And this is going to be
a bit more complicated
than the previous example, of course.
It builds on top of it.
And we're going to talk about
it one part of the time.
So the first thing that we need to
do is actually run the server here.
So Flask, OK--
OK.
So I'm using a library here
called the Flask-Session.
We're going to talk
about the sessions soon.
But I'm using a library called
Flask-Session to keep track of,
you know, if the user's
logged in or not.
And this library actually needs
to be installed separately.
And so to do this, I'm going to do
like I did last time with Flask,
but in this case pip3 install
flask-Session like this.
And it should hopefully
install without any problems.
OK.
I think this is done.
COLTON OGDEN: [INAUDIBLE] your
terminology is just so small now.
KAREEM ZIDANE: Yeah,
somewhere I can see anyway.
OK.
All right, so now I'm running the
servers, no problems, which is good.
It looks a little bit different.
The layout file is pretty much the same.
There's a couple of things that are
different that I'm going to show.
Index file is mostly also
the same, except that--
let's actually look at it.
So tabf templates index.html--
so it extends index.html
like the previous one,
except that it has some
sort of logic here.
First of all, it checks.
If there is a user name, then show
hello and that user name and then
show a log-out link, right?
Otherwise, show hello there and show
a log-in link or a register link.
And this is what I'm seeing right
here, because I'm not logged in.
Makes sense?
COLTON OGDEN: Yeah.
KAREEM ZIDANE: OK.
So let me try to register
myself, because this
is a different application.
We don't have the same file here.
So let's do this.
And hopefully, it won't
show the 500 again.
Because it might be the same file.
OK, good.
So now when I click
Register, what actually
happens is that it shows me back that,
hey, hello user name, KZidane, my user
name, and then a log-out link, right?
And if you look at the
file again, we'll find
the row that corresponds to my user.
So what actually happened here?
So when the form data was
submitted to register,
what actually happened is that--
let's ignore this first
part for a second.
We should've covered this in
a previous example, actually,
but I forgot to do that.
So let's actually talk about it here.
So the first thing that
happens is that if we
get a get request,
what's going to happen
is I'm going to render the register
template with the title register,
right?
And this does something as simple
as rendering the registration
form that we saw, right?
Otherwise , which means
if you get a POST request,
we are going to try to get
the user name from the form.
We're going to try to give
the password from the form.
And then we're going to ensure that
these actually have some value in them,
right?
They're not either missing or have
an empty value like it did before.
And if that's the case, we're going to
abort with HTTP status code for 400.
COLTON OGDEN: Right?
So that's not a not found error.
This is a different error in this case.
KAREEM ZIDANE: Correct.
So 400 is actually a bad
method or a bad request error--
COLTON OGDEN: OK.
KAREEM ZIDANE: --and some useful
description to show the user.
COLTON OGDEN: Which means we didn't
give it the right information,
the POST request was missing
some piece of information
correct and then we're going to
ideally the user gets the row that
corresponds to this user name, right?
And if there's no such row, that users--
actually, so it gets the row that
corresponds with this user name.
And if such row exists, that means that
we have this user name from before.
So we can't re-register it again.
And in this case, we return another 400
with a different descriptive message
hopefully.
And then after that, if
all our checks passed,
we start by inserting a row into
the user's file that essentially
consists of the user name and password.
COLTON OGDEN: OK.
Got it.
KAREEM ZIDANE: All right.
COLTON OGDEN: Makes sense.
I think we have a couple
things in the chat here as well
KAREEM ZIDANE: OK.
COLTON OGDEN: Yeah, no. [? Andre ?]
was clarifying about C++ templates.
Yeah.
I think I mean I think that the
terminology is fairly similar.
But, again, I think the difference
between things like templates in C++
versus Flask is that C++ is creating
an entire lookup table of functions,
whereas Flask, its goal is to distribute
just one bit of information that gets
rendered to you.
But, yeah, in the same sense that you're
injecting sort of place holder values
and then generating some block based on
that, yes, the terminology is similar.
"Are we going to cover Django,"
says [? JL97. ?] Not today.
Maybe in a future stream we might cover
Django, but today is just on Flask.
And saltyglowstick was saying, they
did some research on why app is equal
to Flask__name.
And it was saying the __name variable
provides the name of the package.
And then Flask uses this value to find
out what the location of the package
is on disk, so it can locate
other files in the same directory.
KAREEM ZIDANE: That is correct.
I mean, we're not really going
to care about this right now,
because we're not trying to find files
by location relative to this package
name or relative to the module
name that we're using right now.
But that is a correct
explanation I think.
COLTON OGDEN: "I really
like these examples.
Where can I find them?"
And then [? Bela ?]
actually linked to your--
this is correct, right,
kzidane/flask-stream?
KAREEM ZIDANE: Yup, that is correct.
COLTON OGDEN: That's today's code.
Yeah.
So if you want to follow
along with all these examples,
follow the link that's
actually hidden right now.
Oh, Kareem is going to plug
it right here in the chat.
KAREEM ZIDANE:
://github.com/kzidane/flask-stream.
COLTON OGDEN: Nice.
KAREEM ZIDANE: All right.
COLTON OGDEN: So check
that out, clone that.
It will be good.
And then lastly, "is there a
session on deploying using Docker?
He should cover it in a
different class, Docker session."
And then, actually, yeah, we did.
David and I did a very brief Docker
tutorial, not very brief I should say.
KAREEM ZIDANE: But I think
he's asking about deploying
[INAUDIBLE] applications using Docker.
COLTON OGDEN: Oh, I see.
Yeah.
KAREEM ZIDANE: So containerizing
[INAUDIBLE] applications maybe
[INAUDIBLE]?
COLTON OGDEN: I don't think we covered
that, but, yeah, maybe in the future.
Something like that.
KAREEM ZIDANE: Yeah.
Maybe we could demonstrate that
using Heroku or Elastic Beanstalk
or something.
COLTON OGDEN: Yeah, that could be
useful to some people I think certainly.
KAREEM ZIDANE: All right, so this part
that I just explained in the register
function is exactly the same
as the previous example, which
I forgot to explain.
The extra part is actually remembering
that the user is logged in or not,
which didn't happen
the previous example.
COLTON OGDEN: OK.
KAREEM ZIDANE: And for this, we're
going to use something called a session.
COLTON OGDEN: Right.
KAREEM ZIDANE: And so the
way a server remembers
whether some user is logged in
or not is by sort of giving them
a unique identifier when they log in.
COLTON OGDEN: Right.
KAREEM ZIDANE: Right?
So in the response, it gives them a
unique identifier, a cookie, right?
And then when the browser tries to make
another request to the same server,
by default, it tries
to send that cookie.
COLTON OGDEN: OK.
KAREEM ZIDANE: Right?
And so the server gets that cookie
again, gets that identifier again,
and knows that, hey, this
belongs to this user.
And so it retrieves all
the information about them
and shows that they are
logged in in this case
and greets them with their user name.
And so the way to initialize a Flask
[INAUDIBLE] session is really simple.
So from Flask, we should
import session, as we see here.
Right?
And then the package that we were
using is actually Flask-Session, right?
And then we're going to import
Session with a capital S here.
And then we're going to instantiate
this Session class that we imported
and then pass it app.
And so this is the way
we initialize the session
in this case or Flask [INAUDIBLE]
using sessions in this case.
There's also a couple of session
configurations in this case.
I'm using my file system as
opposed to-- so I'm not storing,
essentially, the data on the client
side or on the user's computers
or the user's devices.
I'm storing the data actually
on my server on my file system
and distributing some
kind of unique identifier
that sort of references this data.
And I just don't want my
session to be permanent.
I don't want them to last
forever in this case.
COLTON OGDEN: Also, thank you for--
I don't know if I'm
pronouncing this correctly--
[? Frefa ?] or [? Fr3Thou, ?] Treet_top
and codekip, thank you very much.
KAREEM ZIDANE: And so a
session essentially ends
up being a simple Python
dictionary, right?
And so to insert a value
in that dictionary,
we just use the bracket notation.
In this case, we're
inserting a key called user
name with a value user name.
But, ideally, you can remember
pretty much anything here.
You can remember their ID
instead if we have such thing.
Unfortunately, we don't use an ID here.
But, ideally, that's the
thing that's remembered,
a numeric number that
identifies a user, right?
After remembering that the user
is logged in after they register,
we just redirect them back to index.
And when they go to index, this
is what's going to happen, right?
Let's actually take a look
first at the index function.
And the index renders
the index template,
passes in the title, like last
time, and then passes in a user name
from the session.
COLTON OGDEN: Right.
KAREEM ZIDANE: So if there's
a user name in the session,
this is going to be the value
of this keyword argument.
Otherwise, it's going to be none, right?
And this is what it checks for.
If the user name exists,
show this specific greeting.
Otherwise, show the log-in
or register message.
Cool?
COLTON OGDEN: Makes sense, makes
sense-- lot of session import worries
in there, three different ones.
KAREEM ZIDANE: Yes.
COLTON OGDEN: It's pretty funny.
KAREEM ZIDANE: All right.
COLTON OGDEN: [? Jiban ?]
was asking, "are you
going to cover the security
issues of sessions?"
KAREEM ZIDANE: Am I going to cover
the security issues of sessions?
Not really.
I believe [? Theodore ?] mentioned
once on one of the streams,
I mean, probably the most common
security issue with session
is called session hijacking.
And this happens by means of stealing
someone's cookies and using them.
COLTON OGDEN: Using them
to authenticate the server.
KAREEM ZIDANE: And so you appear to that
server as that person, but you're not.
COLTON OGDEN: Makes sense.
KAREEM ZIDANE: So we're
not really going to go
into much more details about this.
But this is the basic idea of hijacking.
COLTON OGDEN: If anybody wants to
try and steal Kareem's cookies--
KAREEM ZIDANE: Yeah, feel free to.
All right, so the log-out function,
which happens here when we visit
the /logout, just clears the session,
so forgets that the user is logged
in and, therefore, logging them out.
COLTON OGDEN: OK.
KAREEM ZIDANE: Right?
So it's as simple as that and then
redirects back to the Index page.
Show I click this link, I
should see the message that
appeared if no one is logged in again.
COLTON OGDEN: Correct.
KAREEM ZIDANE: All right.
COLTON OGDEN: [INAUDIBLE] says, "thank
you very much for the follow-up."
And then [? Andre ?] was making a joke.
"Stealing someone's cookies?
What are they, monsters?"
Because Cookie Monster.
KAREEM ZIDANE: Yeah, well.
COLTON OGDEN: "Can you use JS
frameworks with Flask" says [INAUDIBLE]??
KAREEM ZIDANE: In what sense?
I mean, I know Flask
probably has a JavaScript
framework that sort of
wraps some functionality
in like the URL for something.
I haven't used them much.
But, yeah, I'm not going to
use any today unfortunately.
COLTON OGDEN: If they're referring
to maybe using Flask and JavaScript
together just in the
normal sense, then you
can use JavaScript with
any back end framework?
KAREEM ZIDANE: They're just
run in different contexts.
COLTON OGDEN: Yeah.
KAREEM ZIDANE: So the Python
code that you have is actually
a run on the server side, but
the JavaScript code is actually
run on the client side or inside
of your browser or something.
COLTON OGDEN: Right.
KAREEM ZIDANE: But,
yes, I mean, if you're
referring to any JavaScript framework
or any JavaScript code in general,
there should be no problem using that
with a Flask application in this case.
COLTON OGDEN: People are
saying that, recently, there
was the cookie session hijacking with
Facebook, [INAUDIBLE] brought that up.
And then some other folks
were mentioning that as well.
KAREEM ZIDANE: Yeah.
I mean, some of these issues
happen from time to time.
And you should definitely
be careful about that.
The stream is not,
unfortunately, on security.
So we're not going to
dive too deep into it.
COLTON OGDEN: Yeah.
KAREEM ZIDANE: But it's
definitely an interesting thing
to look into and see how you can protect
yourself like from exploiting yourself
to such attacks.
COLTON OGDEN: And Bagelcrush, thank
you very much for following as well.
KAREEM ZIDANE: Thank you.
COLTON OGDEN: Cool.
KAREEM ZIDANE: All right, so let's take
a brief look at the get user function
that we referred to earlier.
And this is just a helper
function that essentially
opens the CSV files, reads in the rows.
And if it found the user name in one
of these rows, it returns that row.
And that's it.
And so you could get
fancy with CSV files
and use like a sorted dictionary
or DictReader or DictWriter
and sort of refer to these by row
user name or row password if you want.
I'm not going to do that here.
Again, typically, CSV files are
not used for this kind of use case.
We're just using them for simplicity.
So I'm just going to go with
numeric indices in this case.
COLTON OGDEN: xyZed92 and ml_newb,
thank you very much for following.
KAREEM ZIDANE: Cool.
All right, so now that we
have a web application that
allows us to register or log in or
log out, what should we do next?
COLTON OGDEN: Well, then
you'll see separate information
when they're logged in, right?
Are we showing their name so far?
KAREEM ZIDANE: Are we
showing their name so far?
Yes.
COLTON OGDEN: OK.
KAREEM ZIDANE: This should
be like when they log in.
I forgot my password.
It's 123, I guess?
COLTON OGDEN: Hard password to--
OK.
So that's working.
KAREEM ZIDANE: Yeah.
They should see yours once they log in.
COLTON OGDEN: So I
guess maybe some other--
so I guess whatever the goal is
of this application, which was--
KAREEM ZIDANE: Right.
We're probably not going
to transition to app4,
which is I think the last
example in this stream.
But I just wanted to
mention quickly that--
let's see.
I think we talked about
all of these except log-in.
Log-in, essentially, is
the same as register,
except that it actually gets
submitted to the /login route.
And the button is called the Log-in
instead of Register, of course.
And if we look at the log-in function
or the function that handles this /login
route, it's also pretty much
the same as register as well.
If you receive a GET request, it
would render the log-in template.
Otherwise, we get the user
name and password from the form
and validate them doing
some sort of validation,
check that we have a record of a user,
and check that actually their password
matches in this case.
And then if everything is OK, we
just remember them in the session
and redirect them back to index.
COLTON OGDEN: Cool, sounds good.
KAREEM ZIDANE: Otherwise, be sent
a 403, which is unauthorized.
COLTON OGDEN: What is it,
invalid user name and password?
KAREEM ZIDANE: Yeah.
COLTON OGDEN: Unauthorized?
KAREEM ZIDANE: Yeah.
I'm trying to remember the control.
COLTON OGDEN: Unauthorized makes sense.
That sounds like something
that they would write.
KAREEM ZIDANE: So this is another HTTP
status code that we can send in case
the user is trying to do
something that they're not
authorized to do right in other words.
COLTON OGDEN: Right.
[INAUDIBLE] was saying, "use
bcrypt for your passwords."
KAREEM ZIDANE: Yes.
You could use any hashing.
I'm not familiar with bcrypt.
But you could use any
sort of hashing libraries.
And I think by Python has actually
built-in hashing mechanisms.
COLTON OGDEN: Yeah.
KAREEM ZIDANE: So you
can pretty much do that.
I just didn't want to
complicate things, to try
to focus more on Flask side of things.
COLTON OGDEN: Oh, it's
forbidden is what 403 is.
KAREEM ZIDANE: Forbidden, yes.
Not unauthorized, it's forbidden.
Thank you.
COLTON OGDEN: [? JL97, ?] "how would
you prevent against CSRF forms?"
KAREEM ZIDANE: OK.
So people are trying to drag this into--
COLTON OGDEN: Cross-Site
request Forgery, I
believe that's what that short for.
KAREEM ZIDANE: Yes.
COLTON OGDEN: Flask has a
module for that, doesn't it?
Or like a built-in
feature for that, CSRF?
KAREEM ZIDANE: I think some browsers--
OK.
So there are different ways to protect
against these kinds of attacks.
I think some browsers have
some built-in mechanisms
of sort of preventing some JavaScript
from some other origin or domain
to be executed on your domain.
COLTON OGDEN: Yeah.
KAREEM ZIDANE: so I'm not sure if this
is a different kind of attack or not,
but some web apps sort
of include a unique token
in the form to be submitted that's valid
for a specific duration or something.
So they use that as well.
Does Flask have something
built-in to [INAUDIBLE]??
COLTON OGDEN: Yeah.
It looks like there's a Flask
WTF, interestingly enough.
KAREEM ZIDANE: What The Form.
COLTON OGDEN: Yeah, What The Form--
which has a .CSRF.
And you can import CSRF protect.
And then you have to instantiate that.
You have to wrap your app around that
basically just how you do a session.
KAREEM ZIDANE: Yeah.
Yeah.
I mean, I have to look
into this more honestly.
But I believe it injects some
kind of hidden sort of input
with some unique value
that it then verifies,
so that no one can sort
of submit this form--
COLTON OGDEN: Yeah.
KAREEM ZIDANE: [INAUDIBLE] were.
COLTON OGDEN: Yeah, you do.
You use a hidden form that has the
token injected into it by the server.
KAREEM ZIDANE: Yeah.
COLTON OGDEN: "You guys should
give an included security session."
KAREEM ZIDANE: Yeah.
Definitely, yeah.
That would be a cool idea
for a security stream.
COLTON OGDEN: David's like
an expert on security.
So I sort of feel like he'd be
great to do a security stream.
I'm not that great at
security, one day maybe.
KAREEM ZIDANE: Yeah.
COLTON OGDEN: I'll ask him if he wants
to do like a basic security stream,
because that'd be pretty fun.
KAREEM ZIDANE: All right, so the last
example that we have today is app4.
And app4 essentially builds on
top of app3, but also adds--
let me actually run Flask here like
last time and then show app here.
So it's mostly the same as the pie
from app3, except that, first of all,
it adds the flash message.
So let me actually show this,
because this might be useful to show.
So if I go back into my app3
folder and I run Flask again--
and let's suppose I'm logged in already.
If I visit register with a lowercase--
OK, so I added this
functionality to app3 as well.
COLTON OGDEN: It looks beautiful.
KAREEM ZIDANE: So this
message shows up here.
You can't actually register a user.
Or we chose that you can't register
a user if you're logged in already.
So you must log out first.
COLTON OGDEN: So this is a flash
message that you're just included?
KAREEM ZIDANE: This is a
flash message that, you know,
it appears as an ordered list item.
And the way this is implemented is--
COLTON OGDEN: It's a list in case
you want multiple flash messages?
Is that why you shows a list?
KAREEM ZIDANE: Correct, yes.
COLTON OGDEN: OK.
KAREEM ZIDANE: Yeah.
You can flash multiple messages.
And they would, in this
case, show as a list.
[INAUDIBLE]
COLTON OGDEN: I love that unstyled HTML.
It's gorgeous.
KAREEM ZIDANE: Yeah.
I hear you're going to
do a steam on CSS soon.
COLTON OGDEN: Yeah, tomorrow.
KAREEM ZIDANE: So maybe
you should do that.
COLTON OGDEN: We're going to do a
basic CSS stream tomorrow at 1:00 PM.
So tune in for that if you're
curious about a little bit of CSS.
KAREEM ZIDANE: Yeah.
As you can see, my apps
are really, really ugly.
So I'm going to watch your stream.
COLTON OGDEN: Mine are, too.
Don't worry.
I'm not very good at CSS,
but I know the basics.
So we'll have a nice lovely
stream on it tomorrow.
We'll talk about just
some of the basic stuff.
KAREEM ZIDANE: We have a
little bit of CSS in app4.
We're not going to dive deep into that.
We're going to leave it to you.
But the idea of flash messages is here.
So in the register routes, if there's
a user name already in the session,
so if there's a user logged in,
I'm just going to call flash.
And flash is imported
from Flask as well.
COLTON OGDEN: OK.
KAREEM ZIDANE: Right?
And then I'm going to pass it
some string here-- in this case,
this string has a piece of HTML--
and redirect back to index, right?
And so the effect of that
is that this flash message
is going to show up in my Index
page or any page in this case
because I've actually added
this logics and layouts.
And much like we have if
statements with Jinja--
COLTON OGDEN: Right.
KAREEM ZIDANE: --we also
have for loops logic--
COLTON OGDEN: Iteration.
KAREEM ZIDANE: --in this case.
So if you read the Flask
documentation, you'll
find the snippet of code that tells
you how to consume your flash messages.
And in this case, you get
the get_flashed_messages.
And you check if there are messages.
You just loop over them.
So this syntax for a
for loop in Jinja is
fairly similar to the syntax
of a for loop in Python.
COLTON OGDEN: Yeah, it looks
pretty much like they took Python
and, with a couple of exceptions,
they put it between percent brackets.
KAREEM ZIDANE: Correct.
And there's no column here.
Like, the indentation-- excuse
me-- doesn't really matter.
So in this case, we have to have an end
for, end if in case of an if statement.
So these are [INAUDIBLE].
COLTON OGDEN: I like how it has context
managers, too, though, the with.
KAREEM ZIDANE: Yeah.
COLTON OGDEN: That's pretty cool.
KAREEM ZIDANE: Yeah.
It's really fancy.
So, yeah I'm essentially in looping
through all these messages using
a loop in Jinja and then displaying
or rendering each message,
passing it to a Jinja filter safe.
COLTON OGDEN: Right.
KAREEM ZIDANE: Because I know my message
actually include special characters,
include HTML.
COLTON OGDEN: So HTML escapes.
KAREEM ZIDANE: Correct.
COLTON OGDEN: OK.
Nice.
KAREEM ZIDANE: So this actually
says that, hey, trust this message.
I know what I'm doing.
This has HTML in it.
Otherwise, it would actually
show the literal HTML.
COLTON OGDEN: Oh, I see.
OK.
Yeah, makes sense.
KAREEM ZIDANE: Yeah.
It would really escape this
and show the angle brackets.
COLTON OGDEN: So it's
actually not escaping it.
It's actually giving it as raw.
KAREEM ZIDANE: Yes.
COLTON OGDEN: OK.
That makes sense.
KAREEM ZIDANE: Correct.
All right, so in app4, which
is this file right here,
we have the same registration
log-in, the same log-in, log-out.
And the thing that we added-- and let's
actually run the [? app4 ?] [? surf ?]
application.
So if I reload this, I actually--
OK.
I saw a bug here, but never mind.
So we see-- and this
is sort of a spoiler--
no posts yet.
COLTON OGDEN: Font's different
there, too, it looks like.
So you got a little
bit of styling there.
I like it.
KAREEM ZIDANE: Yeah.
Yes.
COLTON OGDEN: Oh, did
you include Bootstrap?
Is that what that is?
KAREEM ZIDANE: I don't not.
COLTON OGDEN: Oh, OK.
KAREEM ZIDANE: I just included a
couple of style properties and values.
COLTON OGDEN: Got ya.
A little bit of fancy
hand-written CSS, you know?
KAREEM ZIDANE: So let me register
you, or register me really,
because I'm going to
post on my behalf, right?
COLTON OGDEN: What's on your mind?
KAREEM ZIDANE: So once
I'm registered in,
I have this form that looks familiar
to that of other social media websites.
And the idea is that I will be
able to, hey, post something.
You know, I was on
Colton's stream today.
COLTON OGDEN: That's right--
or I'm hungry today.
KAREEM ZIDANE: Or I'm hungry.
And post it.
COLTON OGDEN: Or both.
KAREEM ZIDANE: And it
would show up like this.
COLTON OGDEN: Oh, nice.
I like that.
I like that.
Now, is this all client
side at this point?
KAREEM ZIDANE: Not really.
COLTON OGDEN: Are you storing these?
KAREEM ZIDANE: I'm redirecting,
but it's really fast
that it didn't like take
a long time loading?
COLTON OGDEN: No, but I mean are you
storing these posts in a database?
KAREEM ZIDANE: I am.
Well, I'm not storing
them in a database.
I'm storing them in the
CSV file like we did.
COLTON OGDEN: Oh, OK.
KAREEM ZIDANE: But, ideally, yes.
You would be storing them in a database.
COLTON OGDEN: Interesting.
Is in a separate database
from the registrants?
KAREEM ZIDANE: That is correct.
And so much like you would have a
separate table for posts than users,
I have a separate file here called
post to CSV that essentially
includes the content of the post--
COLTON OGDEN: The user
name and the timestamp.
KAREEM ZIDANE: --the author of
the post, and the timestamp.
Yes.
COLTON OGDEN: OK.
KAREEM ZIDANE: And then if
we take a look at the user,
it's exactly in the
same format as before,
nothing different, nothing fancy.
COLTON OGDEN: So does your logic
then iterate over the table of posts
and just all the ones that
have the same user name?
It'll just output them?
KAREEM ZIDANE: That is correct.
So let's actually see what happens
when we see the Index page.
So when we go to the
Index page, what happens
is that we render the
index.html template.
We pass in the title as usual.
We pass in the user name as usual.
And then we pass this extra thing called
get_post or posts, keyword argument.
And the value of that is get_posts.
So let's take a look at get_posts.
Right here, we're opening
the post CSV files.
We're reading all of it.
And we're sort of returning,
liking massaging this data
and returning it as a list in Python.
So we take the first cell
in each row and pass it
as the value of the content key,
second cell author key, and third cell
is the date time, right?
Otherwise, if there
are no posts, we just
return an empty array or empty list.
COLTON OGDEN: Cool, makes sense.
KAREEM ZIDANE: OK.
COLTON OGDEN: I can see it as
being very performance heavy
if you had like 10 million posts.
KAREEM ZIDANE: Definitely.
And this is why--
COLTON OGDEN: This is
why you need a database--
KAREEM ZIDANE: This is
why you need a database.
COLTON OGDEN: --with indexing.
KAREEM ZIDANE: And even
if you have a database,
this is why you should limit
whatever you're showing to the users.
COLTON OGDEN: Yeah, like 10 at a time.
KAREEM ZIDANE: Facebook doesn't show
you billions and billions of posts
once you [INAUDIBLE].
COLTON OGDEN: It feels like it.
KAREEM ZIDANE: Well, yes.
But it actually asynchronously
loads more posts as you scroll down
or whatever.
So let's actually take a look
at the index.html template.
And if you go to that one,
the content has the few things
that are different in this case.
Let me indent this correctly,
so that we can see better.
Well, I don't think it would matter.
So it chose something similar
to before when you're logged in,
hello user name if you're logged
in and then hello [INAUDIBLE] link.
But there's also this form right
here that's submitted to /posts.
COLTON OGDEN: Right,
that's the text area.
KAREEM ZIDANE: Correct--
using the POST request method.
And there's the text area
where we type our post here.
And there's a placeholder.
COLTON OGDEN: It's an amazing
placeholder message as well.
KAREEM ZIDANE: Yeah, well, thank you.
It didn't come from scratch.
COLTON OGDEN: Very enthusiastic.
KAREEM ZIDANE: Yes.
And so there's a Submit
button with post on it, right?
And so what happens when
you submit a form like this?
The first thing that happens is
that we get the content of the post.
And we make sure that there
is a user already logged in,
because we don't want to allow
arbitrary people, like anonymous people,
on the internet to post something.
So we get the author of the post.
And we validate that.
We see if there is no post
or, if the post is empty,
show that this is a better request.
If there is no author or if
there is no one logged in,
show forbidden, 403, with some
descriptive messages here.
And then like we did with registering
users, we just open the CSV file.
We insert a row in this case.
The content of this row
is the content of the post
plus the author, the user who's logged
in, and then the current time and date.
COLTON OGDEN: Cool.
KAREEM ZIDANE: And that's
how we store this, right?
And so this is, I think,
all what I have for today.
We can demonstrate this more.
We can have, you know, it was good.
COLTON OGDEN: In case
anybody was curious.
KAREEM ZIDANE: If I reload
this page, it should--
COLTON OGDEN: Nice.
KAREEM ZIDANE: --technically
show the same thing.
COLTON OGDEN: It loads
it all at the beginning.
That's cool.
KAREEM ZIDANE: And so
this is the first step
on creating another social network.
COLTON OGDEN: Yes.
It'll be the next Facebook--
KAREEM ZIDANE: Yes.
COLTON OGDEN: --the next, you
know, sort of usurper of Facebook.
KAREEM ZIDANE: So, yeah, I hope that
was useful for a quick introduction
to Flask today.
COLTON OGDEN: Yeah, that was awesome.
Thank you so much.
We'll catch up with all the chat here.
KAREEM ZIDANE: Thank you.
COLTON OGDEN: Then we'll close it up.
People are saying they're
waiting for the CSS stream.
"Should I learn Flask or Django,"
says [INAUDIBLE] or [INAUDIBLE]..
KAREEM ZIDANE: Django,
I think, is a bit more
difficult to use or get started
with than Flask at least for me.
So if you don't need Django, if
you don't have a specific use
case that you need Django for,
probably start with Flask--
easier, simpler, quicker.
COLTON OGDEN: [? Frame ?] [? of ?]
[? Ref, ?] "where can I keep track
of upcoming sessions?
Go to facebook.com/cs50, which
I'll type here in the chat.
KAREEM ZIDANE: Whoops, that's slash--
COLTON OGDEN: Whoops.
And if you go to this URL, you
can see all the events and videos
that we have coming up.
But I'm also going to work on getting
a schedule integrated into the Twitch
site as well.
So thank you for the question.
"Are you going to talk about Bootstrap
tomorrow," says [? Bavik. ?] Not
Bootstrap tomorrow, no.
Tomorrow is just going to be raw
CSS and pretty simple ultimately.
If you're already
familiar with CSS, it's
probably going to be old hat for you.
It will open us up to be able to do more
a advanced CSS stream in the future.
But, no, it's going to be pretty basic.
No Bootstrap.
Bootstrap we'll have
as a separate stream.
"I get intimidated by CS-only tags on
CodePen and some crazy 3D animation
using a ton of CSS," says
[? NACL ?] [? Eric. ?] Well,
I hate to disappoint you, [? Eric. ?]
But tomorrow we are not going to be
doing 3D animation in CSS.
I wish I was that skillful,
but unfortunately I am not.
But, you know, maybe in the
future if I find somebody here
that's just amazing at CSS,
we can have a follow-on stream
which does some of that crazy stuff.
KAREEM ZIDANE: Can
you be amazing at CSS?
COLTON OGDEN: Me?
KAREEM ZIDANE: Anyone?
COLTON OGDEN: Oh, can you?
Oh, yeah.
The people on CodePen
that do this stuff,
I'd say they're probably amazing at CSS.
KAREEM ZIDANE: Wow, OK.
COLTON OGDEN: "Flash
versus Django, everyone
says I should learn Django
for fast development.
What are your thoughts on that?"
Kind of the same question
as before, right?
KAREEM ZIDANE: Yeah.
COLTON OGDEN: Yeah.
I could see Django being fast if
you're really familiar with it
and you ship all the time with
it and you have a workflow.
But I think if you're in
brand new to that ecosystem,
it's probably more time to get
started with Django than Flask.
Because Django is just so much
bigger, so much more robust.
There's a higher learning curve,
same with Rails, for example,
being a pretty large framework.
"Does Flask code appear on the browser
page source," says [? olegasemi1376? ?]
KAREEM ZIDANE: That's a great question.
No, it doesn't.
So this is actually something
that we should have explained.
When you call render template on the
server side, what it actually does
is that it loads your template.
It sort of processes it,
so it resolves the extends
whatever with the actual
base HTML file that we have.
It plugs in all the necessary values
that we plugged in using our code.
And at the end, it
produces a big HTML file
with everything processed and resolved.
And what we end up seeing is actually
the things that we care about here.
So there is no Jinja syntax here.
There is no Python specific syntax here.
All of it is actually the
code that we [INAUDIBLE]..
COLTON OGDEN: It serves it
just like a regular HTML page.
It looks like it was
completely hand-written--
KAREEM ZIDANE: Yes.
COLTON OGDEN: --by somebody.
KAREEM ZIDANE: So this is often
referred to our server-side rendering.
There's also client-side rendering,
which is you can do something like this
similar with a front end
framework like React or--
did we cover React?
COLTON OGDEN: Brian covered
React, some basics of React, yeah.
KAREEM ZIDANE: Brian covered it, yeah.
So you can maybe look at Brian's
stream for a React tutorial
and see how you can do
client-side rendering as well.
COLTON OGDEN: "I'm eager for
two sessions, one on databases
and two on Heroku slash Docker
deployment," says [INAUDIBLE]..
Yeah.
That's be cool.
KAREEM ZIDANE: Yeah.
COLTON OGDEN: "People are saying that
the hardest thing about making APIs
is designing your data.
Somebody else mentioned it was a
headache deploying my Flask app
on Heroku and connecting the database."
So that'd be cool to talk about.
KAREEM ZIDANE: Yeah.
Yeah.
We should probably talk about
this in the future stream.
It would be interesting.
Of course, you can do this
without Docker at all.
Or you can do it with Docker and
sort of make a couple of things
easier for yourself since the
environments are going to be the same.
But, yeah, that would be something
interesting to look into.
COLTON OGDEN: And then, "the
hardest thing about making APIs
is designing your data."
Again, yeah, that'd be
interesting to have an API stream.
Brian did an APIs and ORMs
lecture for CS50 Beyond.
So maybe we'll get him in
here for APIs conversation.
KAREEM ZIDANE: Yeah.
COLTON OGDEN: And thank you very
much from [INAUDIBLE] and [INAUDIBLE]
and also [? Scout969 ?] for
the follows, much appreciated.
KAREEM ZIDANE: Thank you, all.
COLTON OGDEN: Ba, ba, ba, let's
make sure we're all caught up.
"Thanks Kareem the Dream and Colton.
There we go.
We almost got through
the stream without it.
We almost did it.
No, we got it.
We got it in there.
KAREEM ZIDANE: Yeah, thank
you for watching this.
COLTON OGDEN: "On forms, should
the content type [INAUDIBLE]
type equals be set?" says
[? Jiban3. ?] Encoding type,
I'm guessing, that's short for.
KAREEM ZIDANE: I believe so.
Yes, I think forms have
a default encoding type.
But long story short,
you can sort of submit
the data using different formats.
I think the default
formats, I can't even
remember the names, like duh,
duh, duh, data slash something.
And this is the sort of
key value pair format.
So if you have an input field with
a user name and the value foo,
it will be submitted as
literally user name equals foo.
But there are other for
encoding formats like JSON,
for example, where it would be
submitted as a key for the JSON object.
And the value would be
the foo in this case.
COLTON OGDEN: Got ya.
And [? Andre ?] says, "yes
CSV file-based Facebook
is the next big thing.
I'm sure it'll be very performant."
KAREEM ZIDANE: Wow.
COLTON OGDEN: [? Kiefa ?] is asking,
"how do you implement up-voting
for posts and comments?
What's the logic look like?"
KAREEM ZIDANE: That's a great question.
This will be another piece of data
that you would have to keep track of.
Ideally, you don't really want
to reload the page, though,
when someone up-votes your post.
So this will be ideally
done using an AJAX request.
And so the idea of an
AJAX request is that you
would be sending a request using
JavaScript from your browser
without actually reloading the page.
And the server would receive this
request, process it as usual,
and then maybe change something in your
database or CSV files in this case.
So you would have to keep
track of some counter.
And every time you receive a request
for this particular post with an ID,
you just up this counter by one or
down it by one if you're down-voting.
COLTON OGDEN: "Awesome
stream," says [? Bela. ?]
"Thank you, Kareem and Colton."
Thanks, [? Bela ?] for
tuning in, much appreciated.
KAREEM ZIDANE: Thank you so much.
COLTON OGDEN: "Thank
you for the stream,"
says [? Bavik, ?] much
appreciated for your attendance.
"How would someone go about connecting
React or another front end framework
to Flask?
Will it interfere with the
default Jinja templating?"
KAREEM ZIDANE: Yes.
That's a great question.
And I actually looked
into this briefly before.
And I don't think there is
an ideal way to do this.
Like, it's certainly possible.
It's just going to give you headaches.
Because as you mentioned,
the syntax for Jinja
is going to be problematic
with syntax for React.
And so ideally, that's
why frameworks like React
are typically used with,
I think, a node back end.
COLTON OGDEN: Node back
end with an API, so you
don't have to worry about templating.
KAREEM ZIDANE: So you could
use an Express or something.
COLTON OGDEN: Yeah.
KAREEM ZIDANE: They usually
contain something putting--
I guess you could disable
that, or you could sort of
try to get around it somehow.
COLTON OGDEN: Yeah.
KAREEM ZIDANE: But you're
right, that's a good point.
COLTON OGDEN: [? Hela ?]
from Belgium says,
""[INAUDIBLE] was wondering what
Linux distro Kareem is using."
KAREEM ZIDANE: I'm using Ubuntu 18.10,
which is the latest version of Ubuntu.
Yeah, so it's been working well so far.
COLTON OGDEN: Cool, looks great.
I think that's all the questions.
If anybody has any last
questions, that would be awesome.
[? Kiefa ?] [INAUDIBLE] from
Nairobi, awesome, thank you so much.
"Great session.
Thank you for answering our questions.
See you tomorrow,"
says [? Kiefa. ?] Yup.
See you tomorrow for some CSS.
KAREEM ZIDANE: Thank you so much.
COLTON OGDEN: Yeah.
We'll stick around for just a
couple more minutes in case anybody
has any last questions.
And then otherwise, we will bid
you adieu and see you tomorrow.
Or at least I will see
you tomorrow for some CSS.
And then the day after, we
will review your source code
live on Twitch, so
that'll be a lot of fun.
KAREEM ZIDANE: Yeah.
That's exciting.
COLTON OGDEN: We got to get you in
here again for another stream, too.
KAREEM ZIDANE: Hopefully, yes.
COLTON OGDEN: And as always, many of
you have been contributing your ideas
fantastically.
So keep doing that.
We want to hear all of your
ideas for future streams,
so we can keep producing
some awesome content.
So any topics, anything you
want us to build, anything
you want us to talk
about, that would be nice.
[? JL ?] asking, "where
did you submit the code?"
So do you want to plug your
repo in there one more time?
KAREEM ZIDANE: No, I think he's
asking about the code review thing.
COLTON OGDEN: Oh, right,
right, right, right.
So that is at
bitly/cs50twitchcodereview.
And then [? Frame ?] [? of ?] [? Ref ?]
included the longer you URL that Bitly
actually maps to.
But you can go to either of those.
And there will be a form asking you
for your GitHub repo or a Gist link,
so that we can look at it, make sure
that it's ideally not a CS50 pset
so that we don't spoil the
solution for anybody online.
Also, it's more catered again towards
beginner or intermediate programmers.
It's not meant for bug testing.
So if you have any bugs, we won't be
debugging your code live on stream.
But we will answer any style
questions you might have.
We will be looking at the style,
critiquing it, critiquing the design,
making sure that it's
well-implemented, well-formatted.
And regardless of your experience
level, you know, submit it.
But, again, it's more catered
towards folks that don't necessarily
know maybe how best to
style, or design, or code yet
and are just kind of beginning.
"Gist is adding extra spaces in
the code, anyway to solve it"
says [INAUDIBLE]?
KAREEM ZIDANE: If you're using
GitHub, when you were creating a Gist,
it allows you to choose the number
of spaces to use for indentation.
COLTON OGDEN: Sure.
KAREEM ZIDANE: So if you're using two,
whatever, make sure to choose that.
COLTON OGDEN: Yeah.
And if you're copying and pasting
in the middle of your code base,
that might also be screwing
up the spacing a little bit.
So you can copy it to
another file and Shift Tab it
back to where it's flush
with the left side.
Ideally, the snippet
should have some context.
So maybe just include the whole
function or the whole body.
But you know, either way
send us what you have.
And if we can work with it,
we'll give it our best shot.
[INAUDIBLE], "thank you as always.
You are wonderful."
Thanks so much, [INAUDIBLE],,
much appreciated.
But I think that's it.
I think we're all caught up.
So thanks to everybody
who tuned in live today.
This was Flask.
Thanks to Kareem for
this wonderful stream.
KAREEM ZIDANE: Yeah,
thank you for having me.
COLTON OGDEN: We built a very
simple social network of sorts,
more like a blog at this
point it looks like.
KAREEM ZIDANE: Yeah, correct.
COLTON OGDEN: But, yeah,
no, it was awesome.
So we got to cover Flask.
KAREEM ZIDANE: Thank you so much.
COLTON OGDEN: If you were looking to get
into back end programming with Python,
this is a good starting point.
Tomorrow join us for front
end, more front end stuff.
So last week, we did HTML or
two weeks ago we did HTML.
This week we're going to do CSS.
Tomorrow we're going to do CSS,
Cascading Style Sheets, the basics.
Again, I'm not an expert.
I'm not going to wow you
with my amazing CSS skills,
because I don't have amazing CSS skills.
But I will get you on the right track
if you are an aspiring web developer.
So thanks so much everybody once again.
This was CS50 on Twitch
with Kareem and Flask.
I will see you all tomorrow.
Bye-bye.
