 All right, well, good morning, good afternoon, good evening, depending on where it is in the world that you have to be joining us from. Good and tack, and Buena Sena. And I was trying to learn hello or good evening in Italian, but I think Buena Sena, I think, is right. And Susan is speaking in tongues. Yeah. It's a great way to start. In any event, thank you for joining our little jump start here. This is an introduction to creating websites using Python and Flask. This is a web Wednesday, which, by the way, I'd be remiss if I didn't go ahead and plug the next handful of web Wednesdays that are coming up. You'll notice them on the break slide. We've got a lot of cool stuff as your website. I'm going to be in here doing Angular and MVC with any framework. So a lot of really cool stuff. You'll see all that on the break slides. But what do you say we introduce ourselves and introduce the course and get rolling? Because we got a little bit to talk about today. Yeah, absolutely. Getting out and rolling. Yeah, why don't you talk about yourself? So my name is Susan Eibach. My Twitter handle is HockeyGeekGirl. And my job is I'm a technical evangelist at Microsoft. And what that means is I help developers understand how to get started with our different tools and technologies. A lot of stuff with Visual Studio these days. I am also a Microsoft Certified Trainer. And the first program I ever wrote was on a computer with 64K of memory. So I'm not going to admit to how long I've been coding, but that might give you a hint. Yes, yes. That's a little bit of a giveaway. Absolutely. I've worked with a lot of different programming languages. And I think one of the most important things to realize is as you play with all these different programming languages is that you learn one language as a starting point, and that can take you so many different places. The principles we're going to see today in Python, someday you're going to explore another programming language for web, and you're going to see similarities to what we see here today. Yeah, absolutely. Absolutely. In any event, I guess I should introduce myself. I think so. I am Christopher Harrison. I'm a content developer here at Microsoft, focused mostly on ASP.net, although that's now expanding into an ever-broadening range of web technologies. And Office 365, I was an MCT for 15 years. I guess I still am, but not a full-time MCT like I was. And I got started with a Commodore 64. And I actually wrote a blog post on this in a couple weeks ago, where I talked about the fact that the first main program that I punched in, it was from a copy of an old magazine called Byte. And it was a clone of a popular game. And instead of being able to just type out print, you had to put in the question mark, because otherwise you would run out of memory. So yeah, so quite a little while. And beyond that, you can find me out spending time with my wonderful wife, four-legged child, and running more miles than most people would consider normal, I think. Yeah, good on you. So you do the same, though. Yeah, yeah, absolutely. All right, well, let's go ahead and hit our agenda for the day. So what we're going to start with is actually an introduction to both Flask as well as HTML. So if you haven't played around with Flask, not exactly sure why we chose Flask, what this is all about, we're going to get into that in module one. And then we'll also discuss a little bit of HTML. I am going to say right away, though, that if you're trying to use this to learn HTML, this is really not the best spot, but we'll talk about some resources where you can go get that. Right, because Flask is what's going to allow one of the ways you can take Python onto the web. Exactly. So that's where the connection between the Python and Flask comes in. Exactly, exactly. Yeah, and there's actually other alternatives that you could use as well. There's Bottle, there's Django. We went with Flask. We'll actually talk about why we went with Flask in a couple of minutes. And then from there, we'll go ahead and actually take a look at getting in and creating web pages. And that's going to be our terminology warning section, because that's really where we're going to get into how those requests are going to be mapped and how we're going to control what code is going to get executed behind the scenes. And then all of that is really kind of the appetizer to the main event, the first of two main events, which is going to be module three, where we'll actually build the structure of our little trivia app that we're going to be using for our demos. And that's going to be the front end. So that's going to be the ability to ask the questions and answer them later on, add questions and answer them later on. But what we're going to see is we're going to want somewhere to actually store those. And that will roll us right on into modules four and five, five being the second main event. Right. Where I'm going to go into the back end of things. Because one of the things we're going to see is we get into the websites, is the fact that when you're building web applications, you have to think about what is the user seeing and how do we communicate with the user, as well as when they give us information, how do we store that information, how do we retrieve information on a server side. So I'm going to be talking about the redis aspect and different ways that you can store data so that you can remember what's happening between calls. Absolutely. And then finally, last but not least, we'll have done all this work here locally. Wouldn't it be nice to share this with all of our wonderful viewers and our friends? Well, exactly. Because by default, if I sit here on my computer building a website and I'm running my website and testing my website, it's only available on my machine. You know, I noticed a common phrase throughout all of it. You kept saying website, website, website. I'm thinking we should probably get that onto the, wait, wait, it'll come to me. Oh, we should get that onto the web. Aha, yes. Yay. So exactly. So one of the, so of course we're going to finish off with saying, hey, now that we've built something cool, how do we share that and put it out there onto the great world of the internet, onto the web so others can see it? Absolutely. And that's where we'll close everything off, is actually putting that out there and you'll actually be able to see all of our work. And if you've been following along at home, you'll even actually be able to get in and deploy that out as well. Fantastic. Now that we've talked a little bit about us and what we're going to talk about, let's talk about you. And let's kind of set where it is that we're aiming this. And what we're looking for is really new Python developers that are looking to take that next step. So if you checked out our Introduction to Programming with Python, which is a two-day event, lots of great content, and you may even get a toaster. That's right. You'll have to check that out to find that out. But if you follow along with that, this is really designed to be the next step from there. And then also, burgeoning web developers. So if you're just kind of trying to check things out. But I would also mention that if you've done web forms, if you've done MVC, and you're really just trying to see how things are in other environments. Yeah, because you do hear a lot about Python these days. Yeah. Yeah, maybe you've been developing in .NET for web and you're curious to just explore Python web development. This will be a reasonable course to take you down that path as well. You may be familiar with some of the concepts, because as we mentioned earlier, concepts tend to be the same from language to language. But we will show you things like the routing and so on for Flask and Python and that sort of architecture. Absolutely. And I would say kind of going back to a point that you had made earlier about programming languages having a lot of similar concepts, is that if you've already done C Sharp or VB, a lot of what we're going to be seeing in Python is going to be relatively similar to what you've seen before. And so you'd probably be able to still follow along just fine even if you haven't necessarily done Python. So if you've done another programming language, you can definitely check that out or check this out. Last little thing is, of course, you can go off and get your 50 points. I still, you know, I say this every single time. I do need to update that because it's actually now 2.5 million registered users. Fantastic. Yeah, absolutely. So there's your little voucher code. And I would also mention that it's on the FAQ page as well, which is where you're also going to find our slides. Now, before we launch into module one, I do need to mention one last thing. And this is actually brand new. This is the first live MVA jumpstart that's going to have closed captioning. Right now, it's closed captioning for English. But we do have closed captioning that you should notice on the video stream. And I'm not sure which side of the stream I'm on. I'm seeing comments about the closed caption. So it looks like it's coming up. There's a button like right about there somewhere. I think it's either on this side or it's on that side. I don't know which side of the stream I actually end up on. We don't see the closed captioning. Yeah, we don't see us. But in any event, you will notice there's a little spot right down there that will say captions, and then you can turn that on or turn that off and actually see live closed captioning. But again, this is the first MVA jumpstart doing that, which I think is pretty slick. Yeah, that's awesome. Okay, let me see if we talk about Flask. Yeah, I think that's enough intro. Let's get into the, let's get into the meat of this. Yeah, absolutely. So let's go ahead and introduce Flask. He said in English. So what we want to start off with is really just kind of some level setting here. So what is a web application? You know, kind of start there. And then what is Flask? Why did we go with Flask? And how do we actually get in, get started and do that as we've learned before, that Hello World application? Yes. And then we're gonna close it all off with a primer on HTML. And the main goal with the HTML primer is just to make sure that if you follow along with course one, and maybe you haven't done HTML, that you're now gonna see enough to know what's coming with HTML and how HTML works. Cool, oh wow. Actually, I've just been updated that the closed captions are available in 12 languages. Wow. The live ones? Wow, I thought they were just English. That's what I was just talking about. Fantastic. That is extremely cool. Wow, that's awesome. Cool, all righty. So with that. Hi, now I'm here with Curious, how they translated my Hello Good Evening in Italian got translated. Yeah, yeah. Maybe they translated that back to English. Maybe they did. Okay, at any event, yes, you can expect corny jokes throughout the day. Let's go ahead and talk about what a web application is. And so I pulled this from Wikipedia because of course when you're trying to figure something out, where do you go? You go ask the internet. Yeah, and that will invariably lead you to Wikipedia. So it's a web application, or I'm sorry, a web application or a web app. Is any software that runs in a web browser? It is created in a browser supported programming language such as the combination of JavaScript, HTML, and CSS and relies on a web browser to render the application. That clarifies everything, I think. It clears everything up for me, absolutely. Don't you love it when you get a definition like that and you're like, we're gonna teach you Python and Flask and there's a description, it doesn't use either of those words. But don't worry, it will all make sense. We are gonna bring it all together. So let's translate that into English. Yeah, exactly. So what we're gonna really wind up having with any web application is two main moving parts that we're going to have a client and we're gonna have a server. Now the server, and I always like that restaurant analogy when we're talking about client and server, that when I walk into a restaurant and I sit down at the table, I'm now a client, I'm gonna make requests of a server. The server, or waiter, waitress, whatever term it is that you wanna use there, is then going to take my order, run back into the kitchen, have somebody cook it for me, and then bring that food back out to me. And so that really is that client server. So I'm the one making the requests, I'm looking for whatever it is and the server is gonna go off and do something behind the scenes. And so in our little case with our Trivia app, it's going to be that we're looking to create a brand new trivia question or ask a trivia question. But we could go further into maybe looking up restaurant reviews, maybe posting different updates on fill in your favorite social network here, et cetera. All of those different things are web applications. And again, they have those two same moving parts, that there's a server and there's a client. Now we're gonna focus mostly in on the server side today, and you are gonna notice that there's a lot of different technologies that we can use to create the server side of a web application, that we could use NBC, we could use PHP, we could use Node, or of course we could use Python and Flask, which is what we're here to talk about. I didn't really bother putting that up on the slide. But so Python Flask falls into that server category. Exactly, yeah, if I, yeah, we'll go with, there we go, Python and Flask. That's really important because the client side is really important to realize when you're, when you go open up something like Internet Explorer, which is where we go to do our client stuff, it doesn't, Internet Explorer doesn't understand Python. Right, exactly, exactly. And so you'll notice that regardless of what that server side technology is, it's still gonna work with your browser. And the reason for that is because what you're gonna send out the door is markup and other languages that the browser can understand. So every browser is gonna understand HTML. Every browser's gonna understand JavaScript, every browser's going to understand CSS. And this is a big question that I get from a lot of people who are brand new into web development, is they'll go, oh, okay, well I'm gonna do, let's say MVC. So Microsoft MVC, I'm gonna do MVC, well wait a minute, does that mean that's only gonna work with Internet Explorer? And the answer is no, because you're going to always send down HTML, CSS, and JavaScript, which are things that every single browser is going to be able to understand. So the app that we're gonna build today with Python and Flask is gonna work in IE, it's gonna work in Chrome, it's gonna work in Firefox, it's gonna work in Opera, it's gonna work in... Whatever browser gets invented. Exactly, exactly, yeah. The key thing is whatever server technology you use, and we're gonna be coding in Python Flask as our server, the code it finally sends out to the person sitting at the browser is always going to be HTML, CSS. Now a lot of that's done for you, you don't have to sit there going, oh my gosh, do I have to write every little thing myself? So we're gonna be focusing on Python Flask, though if you're gonna get into more advanced web development you probably will want to learn some HTML, CSS, JavaScript. That's a good next step for you if you're new to web development. We're gonna get you started with minimal HTML, we're gonna do a little bit of HTML, but just with the Python that you know how to use, we're gonna be able to get some websites built. Exactly. Now the last thing to point out here is that there might be other components behind the scenes because let's think about an e-commerce site. And so I go into that e-commerce site and I say, hey, I wanna place an order. So these are websites where I go and order books and things online, yeah. Exactly, yeah, so there's gonna be a lot of other components because after all, when I go in and I say, well, I want that book, they need to send a signal out to the warehouse, they need to send a signal out to the shipper who's actually gonna get it to my house. So there might be a lot of other things that are going on behind the scenes. And I was just gonna like to point that out that it might not just be your little app that you might be incorporating services from elsewhere and bringing all of that in. Cool, well then, what's Flask? Yeah, how does Flask fit into this big picture of, okay, so there's the client, there's the server, there may be a database storing some information? Exactly, yeah. Well, as it turns out, yeah, yeah, it turns out, Flask is a micro framework for Python based on work, Zig. That's good. Forgive me if we're mispronouncing that. Ginger 2 and good intentions. I like the good intentions at the back end there. Okay, well let's try to clarify that a little bit here. So Flask defined, well, Flask is a very lightweight framework and this is one of the biggest reasons why we chose this technology over a couple of the other ones that are out there for Python as the next step because it does what it needs to do and nothing else. That one of the things that I always have a problem with when I'm trying to learn a new technology is sometimes just the entry point requires such a steep learning curve that it just turns me off to the whole thing, that there's just so many different moving parts and there's just so much that's just dropped on to you. You're just going. It's intimidating. Yeah, where do I start? So I need to learn this and this and this and this. And that's one big reason why we chose Flask is it's very straightforward that it doesn't do a whole lot. You can get it to do a whole lot, but out of the box, it doesn't do a whole lot. It's very lightweight and everything as we're going to see is going to be based on components. So out of the box, it does just a little bit and then there's going to be components. So for example, if you want to call those services, if you want to do templating and Susan's going to be very happy about this, if you want to do databases, you can add it in. Yeah, but you start off with basically, hey, I want to display web pages. I want to do a little code. Then go back to another web page. You start off with that and then you add the extra pieces as you're ready for them. Exactly, as you need. So that way you can focus in on, oh, okay, this is all I need to get started. Start building up some strength there and then go to the more advanced topics. All right. So the basic features here are the fact that it is based on Python, which is a nice entry level language, very flexible. And it is also open source. So you can use this to build whatever it is that you might want. So why did we choose Flask? Well, it was for all of those reasons. It's unobtrusive, it doesn't get in your way, that nice low entry point. And it's also a great place to learn concepts. And one thing that we want to stress here is, because it's always one of those trade-offs whenever you're teaching something is, how real world do you want to get, especially at the entry level? Because a full real world application is going to have a lot of moving parts and it's going to take quite a little while to develop. We're going to be going with a relatively simple application here, but you can absolutely 100% use Flask to create full blown real world applications. Now you very well might find after a while as your application starts to grow that maybe you start to outgrow Flask as well, absolutely. But I don't want you to leave here thinking, okay, well, the only thing that I've learned with Flask is just the ability to create a very simple little application. You can absolutely use this to create much bigger applications, create enterprise apps, 100%. All right, well, let's actually get in and get started. Let's start looking at code, I think it's time. Exactly, exactly. So what we're going to need is our different components. We're going to need to talk about environments. We're going to need to talk about the Visual Studio templates and then we'll do Hello Flask. So I promise we're going to get to code. Okay, good, awesome, looking forward to it. Okay, so a couple of things that you're going to need. As it turns out, there's a lot of tools that you could use to write Python code. That's right, you can get stuff for different machines. If you're working on a Mac, you can absolutely download software that will allow you to develop on Mac. But we're going to be using Visual Studio and what you do is you have to install Visual Studio and within it you'll need an add-on to allow you to do Python coding called Python Tools for Visual Studio. So step one, install Visual Studio. Step two, install the Python Tools for Visual Studio. You can get Visual Studio for free. You can get that Visual Studio 2013 community edition. Please do make sure you have the most recent updates applied. And then last, you're going to need to install an interpreter that's going to allow you to execute your Python code. So if you go down to pytools.coplex.com, that website, you can find, if you go to the documentation tab, you can see all those installation instructions, the links to all those tools for you. So that one URL is really useful if you haven't set up your environment yet. You're going to want to do that. Yeah, right up at the top of that page, you'll actually see a little link that will say installation instructions. Just click on that and it will walk you through the whole thing. The one that I do want to highlight here is that Python interpreter. That the tools themselves, just plug into Visual Studio but they don't give you the Python interpreter. Which allows you to actually run your Python code. Exactly, which you're probably going to want to do if you write all of that code. So do make sure that you install that, otherwise you're going to wind up running into a couple of problems. Okay, now we've already highlighted the fact that Flask needs extensions, needs components, needs packages, whatever word it is that you want to use there. You need to add stuff to Flask. Exactly, you need to add stuff. Yeah, we'll just go with stuff. I like it. So you need to add stuff. So that stuff must be installed. Right. So the question is where? Well, as it turns out, you can install this into one of two spots. You can install this into the entire system which is going to make this globally available. But the problem with doing that is sort of two-fold. That number one, it's now going to be globally available and maybe you don't actually want that. But also number two is a lot of the different add-ons that you're going to get are going to be parts of different open source projects. And so they're going to be updated at different times and at different speeds. And anybody who's ever done an update knows that sometimes you'll update one component over here and then all of a sudden this one breaks. Yeah. So having the ability. I know where you're coming from on this one. Absolutely. There's nothing worse than you've got two projects up and running and they're both working. And then somebody makes an update to something. And you can only handle an update in one of the two projects. So it's really wonderful to have this option of not saying let's install, because I might need version two here. I might need version three here. So when you install it globally, you're stuck with the same version for everything. Exactly. Maybe I want version two now, but for this project over here, I want version three. Yep, yeah. So I would say as a best practice, install that into your local environment then. And you'll actually notice that Visual Studio will give you that option that will ask you, okay, well where do you want to install this? Do you want to install this into System Python or do you want to install this into a local environment? And it will give you the ability to create a brand new local environment. And there's my little, here, wait, wait, I need to back this up. I worked hours on this animation. Are you ready? Okay, let's see. Oh, look at that. Wow, you've got like an expanding box. Yeah, I know. You're going to be doing a PowerPoint MVA next, I tell you. Yes, exactly. No, nobody wants to see that. I'm going to do that. Really, install that into your local environment. And now let's actually get in and let's do a demo. All right. So let me bail out of my slides here and let me open up Visual Studio. And it is worth noting here that in the background, we've already installed the tools that we need. So we're just going to be able to fire up Visual Studio and away we go. And I also want to highlight, let's do this. Do, do, do, do, I want, well, I didn't get it in private, but that's okay. That's just what came up. HB colon, whack, whack, github.com, geek trainer, and Flask, that was what I called it. So one of the things that we did over the last couple of days here is we went in and started setting everything up for the demos that we're going to be doing. So you'll actually notice right here, the one that I'm circling down at the very bottom there, that trivia, that's the actual final, hey, we're done. We've also got this is what it's going to look like after module two, this is what it's going to look like after module three, this is what it's going to look like after module five. So if you want to go download that and use that to follow along so that way you don't have to type furiously, you can do that. I'll put the URL back up in one second. But what I want to highlight right here is this download zip. So that way if you don't want to mess around with maybe doing this inside of Visual Studio and connecting to the project and so forth, maybe you haven't done that, just download zip and then away you go from there. I would mention, however, that there is the ability, I apparently can't talk in type at the same time, usually I can. View trainer, whack, flask, there we go. This right here is the URL. I will mention that Visual Studio has the ability to pull this down for you and there is of course an MVA on Visual Studio and GitHub that's worth checking out. So it's actually just called Visual Studio in Git rather than GitHub. Yeah, cool, so we actually had just had a question in the Q&A window asking, hey, where can I get the demo code? So there you go, github.com slash geek trainer slash flask, just pick that download zip file and you've got your own copy. There we go, we'll put it up one last time there. And I put it into the Q&A window as well, so. Okay, yep, yeah, you're probably just gonna want to keep that on copy and paste. I expect this to be one of the people asking that. It's been known to come up again, yes. Okay, cool. All right, so there is that, but let me go into Visual Studio here. And what I'm gonna do is I'm gonna create a brand new project here. So I'm gonna say file, new and project. And then you're gonna notice that I of course have, because I've installed the tools, Python, web, and then there are all of the different web options that are available to me. Now, as we mentioned, you'll notice Bottle Django. We're using Flask, we've chosen Flask. Yep, so we've got Flask here. And then I'm actually gonna sort of sidestep for two seconds, only just because I always feel the need to point this out. A lot of times, you know, people hear Azure and they think Microsoft, okay, well that's good. And then they think, oh, well then I have to do that with C Sharp. As a matter of fact, you don't. So if you want to program your cloud services using Python, you absolutely can, 100%. Yep. Okay, now you're gonna notice that we've got one, two, three, three Flask projects, ah, ah, ah, ah. And you might be wondering which one should you choose? Should you go with Flask Web Project? Should you go with Flask Jade? Or should you go with the blank Flask Web Project? Here's the difference between them. So first of all, the difference between one and two is that the Flask Jade is gonna use Jade as its templating engine as opposed to JINJA. We're gonna be using the JINJA one, so we're not gonna go with that one, but that's the difference between those two. But the main thing about the one and two up there is that they're both built. That was weird. There we go. Huh, it's not letting me type on my screen. Try again. There we go. That was weird. In any event, they both use what's known as Bootstrap. Now Bootstrap is wonderful. There's an MVA on there. Just go to MVAMS. You'll notice if you just search Bootstrap, you'll find the one that John Galloway and I did. We're more than happy to walk you through all of Bootstrap. But Bootstrap is a perfect example of what we were talking about before. It's gonna throw a whole bunch at you that you now kinda need to figure out before you can start writing your code. And again, that steep learning curve we wanna avoid that. Yeah, we wanna get started. We wanna have our first website up without a massive learning curve. Exactly. And so I do love Bootstrap. And Bootstrap, once you learn it, will make your life so much easier. Yeah, it's a good next step. Exactly, yeah. We wanna keep it nice and easy. So we're just gonna go with our blank flash project here. The other big advantage of using the blank one is so many people will ask, okay, well, wait a minute. I went with this template and it threw a whole bunch of stuff in there. And you know how it works, but I don't know how it works. Yeah, I've had that happen before where I create the default project and then I run the default project and it's got like five pages I'm navigating around and then I get lost of what code is where. Exactly. And so I always find it nice when I'm trying to learn to just start with a clean slate. So is this gonna mean more work for me? Absolutely. Because I'm just trying to learn, am I probably going to in the future go with option one there, with that flash web project? Absolutely, but let me start here. Well, because when I'm getting started I'll actually understand everything that's in there. Exactly, exactly. All right, so let's go in and let's call this Trivia MVA. So this will be the one that we'll be building sort of as we go along here. And I've got my little Python flask, the solution name is just fine and let me hit okay. But wait, we're not doing Hello World? Well, we'll do Hello World. I'm just not gonna call it Hello World. All right, okay. Now, this is what I was talking about before, is you'll notice that it says, hey look, this requires external packages. We need to install them. Now here's the great part, you do have to be internet connected, but this will automatically download them for us. So we don't actually have to go out and manually download and unzip them. And we don't know how to know which ones. Exactly. I love the fact it says, you need some packages, would you like me to get them for you? Thank you, yes. Don't make me figure it out. Absolutely. So it's just gonna go off and grab them, but it just needs to know where to put them. And so you'll notice right here that it will say into a virtual environment or into Python 3.4. And remember that this is gonna be shared by all projects. So that was that system option you were talking about. That's that system global option you mentioned earlier. That's exactly it. And then that virtual environment, that's gonna be the private one just for here. That was when you were recommending. Visual Studio even recommend. Even Visual Studio recommends. We all agree on this. Exactly, exactly. Now the one thing that I do wanna highlight, if you remember back to the installation steps that we talked about a couple minutes ago. And I said, hey, look, you're also gonna need the Python interpreter. If you forget to install it, this is where it's going to fail out is right here that it won't create that virtual environment. Because in order to create that virtual environment, it needs Python. So this is where it's going to fail out if it doesn't have it. Okay. With that, I'm now gonna say, install into a virtual environment. It's now gonna say, all right, well, what do you wanna name it? ENVS convention, who am I to argue? It's gonna ask me what version we want. We only have three, four. And I'm just simply going to click create. And then with Blending Speed Amazing Accuracy, it will go off and pull down all of the different packages that we are going to need. And just kinda chug a chug a chug a. Move your mouse, makes it go faster. Or it makes me feel better. One of the other. Sorry, I was just answering a question. Oh no, carry on. I am also kind of doing a little dance in the background here. That's not your usual slide dance. I'm waiting for the slide dance here on camera. I am on camera. Yeah, but it wasn't the slide dance. It was the moving mouse dance. I've always wanted a little crank on the side of my computer just so it would make me feel better. So when I'm waiting, I could turn a little crank and then I wouldn't be able to tell myself I'm helping the computer go faster. Bring back the turbo button. You know what makes sense. Okay, so let's take a look at what we've got here. Now, first of all, it did create this little app py file and I'm gonna get to that. But I'm gonna get to it in a minute. That what I wanna start off with is you're gonna notice over here that we've got our Python environment. There's our little ENV that we just created. And then you'll notice that we've got Flask. It's dangerous. Gintu 2, markup safe, PIP, setup tools and the WorkZig down at the very bottom. So Visual Studio automatically went out and downloaded all of those forming. Nice. Now, here's the thing. I need those here on my computer when I'm doing Flask development. But these packages are global. They're universal. Everybody knows, or Visual Studio knows and that's really I guess the important part, knows that these packages are needed. So let's say that what we're eventually gonna do, like we've already done, is we're going to take this project and we're gonna push this up into GitHub, which we did. Well, we don't need these packages in GitHub because they're the exact same packages for everybody. So there's no reason to keep uploading them into GitHub. Yeah, because we just wanna share the code we wrote. Exactly, exactly. So the problem then becomes, well, let's say, like maybe some of our viewers have done, is somebody's gone out and they've pulled down the project and they're maybe seeing a little bang next to that Python environment and they're trying to figure out, okay, well, wait a minute, this isn't working. What's wrong? Well, here's what's cool. I love this feature because it's true, right? And you guys will run into that actually if you go and get our demo code. If you go take our demo code, take that zip code and try and open it up in Visual Studio, you're gonna get the source code but you're gonna see that that environment's gonna be empty. It's not gonna have the pieces. Because the environment pieces were not uploaded. Now you're gonna show them a trick. Exactly. Now there's a little requirements text file and on this little requirements text file, it's gonna list off all of the different packages that we have grabbed. Now you'll notice the only one in here is Flask and you might be thinking, well, wait a minute, Christopher, I'm no math major but I noticed there's only one there and there's one, two, three, four, five, six, seven items over there and I'm pretty sure that seven isn't equal to one. Here's what's cool is, hey, you know. Seven, one is close, easily mixed up. I forgot to tell you there was gonna be math today. No. But in any event, what you're gonna notice is that all that we have the entry for was just Flask. Well, when you say I want Flask, Flask up on the little Python servers is built to say, all right, well, if you're gonna do Flask, you're also gonna need it's dangerous, Ginger2, MarkupSafe, PIP, SetupTools, and WorkSync. It's- So all those environments that are listed there, it, Visual Studio knows, when you ask for Flask, those are the packages you need. Exactly, yeah, because when it grabs Flask, it's gonna bust that open and Flask is gonna say, well, I also have these requirements. So I also need you to go, grab this one, this one, this one and this one. So that's exactly what we've got going on here. Now, you're gonna have the requirements text file from GitHub, you're not gonna have the environment. Now you may notice a little bang on it and I personally find the easiest thing to do, just hit delete and delete on the environment. So this is kind of what it would have looked like if I'd taken the code from GitHub and just opened up sort of, except I'd seen environment with only one little thing. Yeah, exactly, yeah, so just delete that environment. Okay. And then what you're gonna notice is that I'm gonna right click here on Python environments and I'm gonna say, add virtual environment. So I'm putting a new environment back in. Exactly. And then right down here, so you'll notice it's the exact same screen that we saw before, but I wanna highlight that little text right there. Look at that. It found a requirements text file. So all I have to do is just simply hit create and then get a sip of coffee. So basically it says it's gonna look at the requirements.txt file, from that it's gonna add the necessary components to your virtual environment and now you're off running. Exactly, while you're sipping on coffee. Nice, yep, or water for me. Okay, I need coffee. Okay, I'm this loud and jumpy without coffee, you don't want me with coffee. True story. All right. Susan on caffeine and before people doing closed captioning would, they just lose it. They wouldn't be able to keep up. Fingers flying everywhere. Okay, so anyway, so what you're gonna notice here it's now recreated that environment for me. So that's what you're gonna wanna do. So that's kind of the basic steps there. Now, let's go ahead and focus in on our code now. And so what this automatically did was it created an app pie file, which is by convention the entry point to our application. And so what you're gonna notice is there's a triple quote comment here. And this is for those of you who took the introduction to Python course with us. We used a different convention for comments. The person who made this template chose to use a triple quote convention for comments. Yeah, and it's honestly, it's a little hacky. I'm not a fan of it. Yeah, I prefer the other one. But anyway, it is a comment. Okay. Yep, exactly. So what it's saying is saying, hey look, this is gonna be what's going to host your development server. It contains the definition of routes and views for the application. Okay, cool. Then you're gonna notice this little line here from flask import flask. Right, import we use to access code in libraries. Exactly. So you'll notice from flask. So flask is the name of the package. What do we want? Flask. So this allows us to access the flask code. Exactly. This little part right here is gonna create our application. This underscore underscore name is just hard coded in to just grab the name of the server. Don't worry at all about that. This is one of those things where you can just treat its hat amount to magic. It's just, it's one of those things. It just, it needs to be there. Okay, so this falls into the category of, you know what? This is gonna be created for you. Don't mess with those two lines of code. Okay, exactly. Yep, leave those two alone. And while we're at it, go ahead and leave that line alone as well. And that's just simply going to create a little interface that again is just gonna help serve up our pages. So really, our code starts here. Yeah. We'll just do not touch. There we go. I like that. And our code goes down later. And do not touch. Yeah. There we go. Perfect. Our code. Yes. So now we get to the part where we're really interested in playing around. Exactly. Yep. There's an optional there. So, okay. Now, what you're gonna notice down below here is this little thing called app route, or root, route. Yep. Root. I'll probably bounce back and forth between the two pronunciations. And then you'll notice a little single quote, forward slash, single quote, which of course is a string and a forward slash. Now we're gonna get into routes in the next module. So right now, you can treat this tat amount to magic. But what this is basically going to say, and you know, one of the conventions that a lot of people like to do is they like to actually put out what the URL is that this is going to represent, which in our case would be whatever the name of the server is, forward slash. Yep. And that's it. You do see that a lot. Exactly. And so, you know, you might go in a little bit later, and again, we'll talk about how to do this. And it might be maybe server and then question. Right. And then, you know, maybe server and then create, or you know, whatever it is that it happens to be. A lot of times when you visit a restaurant website, it'll be a slash menu, a slash directions. Exactly. Same sort of thing, right? Exactly, yeah. And slash is sort of the main restaurant page. Exactly. And we're gonna see how to make all of that. Okay. Now, what I'm gonna do for right now is I'm just gonna get rid of that comment because we don't need it. And Susan, I'm gonna put you on the spot here. Oh, okay. And I'm just going to circle or square, I guess, that one little spot right there, just the blue section, just what's inside the blue, what is that? That is pure Python code. Okay. And that is Python code, but it's creating a function called hello and the function we're creating called hello returns a string that says hello world. So there is nothing that's special there. No, that is a standard Python function. That's just hello world. There's nothing extraordinary there. Nope. And this is the biggest point that I wanna make in both this module as well as in the next module is, you know, sort of like, you know, a little girl named Dorothy and, you know, she had the power all along to get home. You've actually had the power to build an awful lot with Flask by learning Python. So if you already took that first Python course, you already have a lot of the knowledge that if you know how to create Python, now it's just a matter of kind of figuring out, okay, well, what methods is this adding in? What components is this adding in? And how do I work inside this environment? But the language is the same. So you're basically expanding your vocabulary if I can just sort of beat that reality into the ground. That's the idea of it. It's expanding your vocabulary. You're expanding your tools. So, you know, think of it as a toolbox. We're adding one more tool to the toolbox. Exactly. We got the Python tool. Now we're adding the Flask tool. Yeah. And together, that allows us to bring it to the website. Exactly, yeah. You're starting to learn all of those different, you know, colloquialisms and all of those different kind of cultural references that, you know, when you're learning like a normal language, I could go off and I could learn French and all the syntax on French and how to conjugate verbs, verbs and all of that good stuff. But if you drop me into the middle of France or you drop me into the middle of Montreal and expect me to speak, there's still gonna be a lot more that I need to learn because I need to learn how to now work inside of that environment. So, you know, as people make different cultural references and, you know, say for example, things like Bob's your uncle or whatever the French equivalent. But my favorite, didali patat, one of my favorite, which means you're way out in left field, you know, middle of nowhere. It's a very Canadian French expression. Yeah, or you're way out in left field. Yeah. And again, you know, that's a very, you know, cultural thing. And the more you understand, the more you can communicate, the more you can do. So in this case, we're expanding what we can do by expanding our coding vocabulary. Exactly, but you still have the basic structure that you still have that basic language. So you still know, you know, there's basic verbs and so forth. So now we're just expanding the vocabulary there. Okay. So now that we've got that little part right there and again, I know I haven't spent a lot of time on that line. We'll come back to it. We're gonna come back to it. And then this line right here or that little block, again, this is all server side code. What this is actually doing is this is launching our server. Yeah. And what do you mean that's launching our server? Well, I'm so glad that you asked this. I'm gonna do this through the menuing system. This, by the way, will be the only time probably I'm gonna do this through the menuing system. I typically just go F5 or control F5, but just to kind of show, I'm just gonna start without debugging here. Okay. Now, what you're gonna notice is I get a little thing saying the project's out of date. Okay, fine. And, all right, let's do two things here. First thing that I wanna do is, since I created a new project, I have to change my color scheme here. Yeah, it's a little easier to read on the screen that way. Exactly. This right here, this is, this command line is our server. This is our server. That's the server that's running our code for us. Exactly. Then you'll notice right here, if you wanna get kind of an Uber technical, it's actually making the little request using HTTP 1.1 and we had a 200 response. So, there is our server. This is actually what's running this. And in fact, you'll notice, if I close this out, by the way, you are gonna notice there's Hello World, let me. All right, okay, we've got our Hello World code on there. I like that. But you'll notice, if I come back to here and I hit refresh, give it a second, you're gonna notice that it's going to fail because I closed that server. That little command line was our server. And that was running our code. So, when we stopped it running, then our website stopped working. Exactly. And so, you'll also notice that we said Hello World. So, let me just go in and update this. Let's say, for example, Hello Susan, just to prove there's nothing up my sleeves, except for my arms. Thank you for laughing at that, Barry. Sorry, it took a second. Well, what you're gonna notice is that sure enough, it now says Hello Susan. So, whatever it is that we return back. Is what's displayed on the webpage. That's pretty boring text, don't you think, Susan? I mean, it's got your name. I know, but I think we could be able to dress it up a little bit. So, we're not limited to just displaying text in terms of what we return. We can do something with it, right? Correct, yeah. Webpages usually look pretty fancy. Exactly. Different colors or bold and italics. Let's get a little better, yeah, exactly. And so, what we're gonna need for that, back to my slides here, with a flourish and everything, is our HTML primer. Yes, because as well as being able to return text, we can actually return HTML. Because really, when you get right down to it, HTML, just text. That's really it, you know? Yeah, and HTML is one of those languages that browsers understand. Exactly. So, that means when we return HTML to a browser, it can say, oh, I know how to display that. Exactly. So, Internet Explorer, Chrome, Firefox, they understand HTML. Firefox. Firefox, Firefox. I'll get there eventually. Maybe I should have had caffeine this morning. You want some coffee? No, I'm good, thanks. All right, so anyway, so let's talk a little bit about HTML and some basic concepts here. So, HTML stands for Hypertext Markup Language. Okay, cool. That's what it is, okay. There we go. So, what this is, is it's the standard markup for creating web pages, and it really consists of two main components, what are known as elements and attributes. Now, an element is going to consist of two tags. An open and a close, where it's going to either describe or do something to what's inside of it. So, in our little case right here, our little body, it's describing, hey look, that's the body. That's what we're trying to display out. The main part of our web page or whatever. Exactly, exactly. It's like the body of a letter, the, you know, of a body of the page, the body of the book, the main part. Exactly, exactly. And so, you'll notice that all of our tags are gonna be contained inside of angle brackets. Yep. Those tags, cause we always get asked this. Case sensitive, not case sensitive. Just treat everything like it is case sensitive. Technically, HTML is case insensitive, but convention is always use lower case letters. It's a good habit also, cause something I'll be talking about this afternoon. Yeah, exactly. Just, you know, it's one of those things, you just wanna get yourself into good habits right away, that, you know, whenever I'm teaching and entering a programming class, I spend, I swear, half the day, if it's a full day, it's not like half of it, just going over good practices, because you wanna learn those skills right away, because that's always what you're gonna lean on later on. So, you know, learn good things. Now, let's talk a little bit about those closing tags. A lot of times you don't need them, because what's gonna happen, and sort of a long story, find me on Twitter and I'll explain the whole thing, but what's gonna happen is the browser's always gonna make a best effort. Yeah, it makes an educated guess. If you leave off a close tag, it says you probably meant to close that. If it can figure it out, it'll just keep going. Exactly, and so the HTML doesn't need to be perfect. Yep, it's very forgiving, but... Try to keep it as good as possible. It's gonna aid the browser, but more importantly, it's gonna aid the developer. And that's you. It's gonna make your life easier if you get in the habit of, yeah, just make everything lower case, close your tags, it'll be easier for you to read, it'll be easier for you to update later when you wanna improve and make changes to your code. That's exactly it. Now, as a result, there are some tags, like BR, which by the way stands for line break, which just simply means go to the next line. Yeah, it just gives you, I use that a lot when I'm building webpages, just makes a blank line between... Yep, exactly, yeah. Two lines or two words. Go to the next line. So technically you don't need to close them. It is still best practice to close it, and then the cool kids, I've been told I'm not a cool kid, put a space forward slash angle bracket as the shortcut to close them. So if you've ever seen that, and we'll be seeing that a little bit later on today, that's what's happening is just the shortcut way. Yeah, because that forward slash is always how we indicate the closing tag. So sometimes it literally is open, closed, all in one string. Exactly. Now, our elements are gonna be grouped together in many types, and there are more elements here than I'm going to stop and list because we'd be here all of today and tomorrow and after that. And there is a full course on HTML, so we're not gonna try and do that. We're gonna give you enough to be able to start playing. Exactly, exactly. And so let's kind of break it down into three main categories here. We've got what are sometimes known as semantic tags, new to HTML5, and they're really just there to describe the data. So this is my header, this is my footer, this is the navigation section. Yeah, they just help the programmers sort of understand the different parts of the page. Well, they also help search engines as well, understand the parts of the page, because when Bing comes along and crawls your page, it needs to be able to quickly figure out what's on the page. And so if we just simply say, hey, look, this is bold, and actually I'm gonna sort of skip to the end here. If we just simply say something is bold, well, what do I know about it? I know it's bold, but that's all that I know. If I see it contained, however, inside a footer, now what do I know? Well, now I know that that's the footer of the page, and now I've got a little bit more of an understanding about what's going on there. So you are gonna notice that there are those format tags, and you are gonna notice that I'm gonna use them today just to try and keep things a little bit simple. But generally speaking, you wanna avoid those, and instead you wanna use CSS, you wanna use style. Which we're not getting into today. Exactly. So we're gonna start you off with, oh, look, you can make change the way things look. When you start building full websites, you can probably wanna use CSS to control the appearance of your web pages. Exactly. In terms of bold, font, color, and so on. That's it, that's it. Yeah, you can actually do all sorts of cool things with it. Yeah. There's an MBA for that. And last but not least is our controls. And again, we're gonna see these a little bit later. This is where we can get things like links and buttons and input tags as well. That we will play with. Yeah, and that's just sort of like a real quick synopsis of some of the different things that are available to us. A standard HTML page is gonna look like this. HTML. Oh, wow. You put HTML in your HTML. I did. Susan, cause of distraction. Cause of distraction. Yes. But I'll mention another neat thing about the header, footer, and nav, those ones we sort of indicate the different sections of a web page, it's kinda cool. So those are also used by screen readers. Yes. So a lot of the tools that, for people who have low vision issues and rely on those ones that speak to them, they actually use those header, footer, nav to help tell a person, hey, this is the header of the web page and the body of the web page as well. Absolutely true. Got a long enough distraction? That was perfect. Okay. So apparently when I was typing out this slide, I moved a little too fast. You know, it's one of the nice things about having IntelliSense and it will automatically fix these things for you. I meant head there. Now, head and header are different. So this is not header, this is head. And inside of head, we can do different things like adding little things to the page, for example, metadata, or in this particular case, adding the title to the page and we'll see where that's gonna be used in a couple of minutes. And then finally, last but not least, is the body. And you'll notice inside the body that I've used a div tag. And this div tag is sort of a generic helper tag that's going to indicate that whatever's contained inside of there, by default anyway, the next div tag will be on the next line, the next div tag will be on the next line, and so forth. So it just allows you to make the code line by line? Exactly. Yeah. In a nutshell, there's other things that could go along with the div tag, but for right now, that's sort of perfect. The last little thing that I wanna mention is attributes, these are key value pairs, and they just allow us to add additional things to a particular tag. So for example, an a tag or anchor tag, which is gonna create a link. So if you clicked on this, where's it gonna go? Dub, dub, dub, dub Microsoft. We use those a lot on web pages. This is how you move from page A to page B to page C. This is hypertext. Yes. There's a little link, there we go. Cool. Let's go in and kind of take a look at a demo here. Yeah, time for some code. Yeah, let's spice up our little page here. And so what I'm gonna do is I'm actually gonna kind of build out the whole thing, is let's say HTML. Uh-huh. Let's say head. So now you're actually typing in action. So instead of just destroying your returning now, you're actually returning HTML, but that's okay because we know that the client, the browser, Internet Explorer, Chrome, or Firefox understands HTML. So it knows how to read this text and display it as per the rules of HTML. Oh, and you're using H1, which is header one. Thank you. That's a tag that HTML understands to display it as a primary header. So it has sort of default ways to display things with H1, but it basically is a header. Okay, now what I'm gonna do here. And I'm getting a high five if you manage to do this without a single typo. Well, fortunately, I kept it very easy for myself. Yeah, that's a lot of open and close angle brackets though. So. It certainly is. Okay, and I'm just gonna try and format this. And I see you're trying to keep everything lower case on your tags. And I can see your closing tags. So you've opened header and then you've closed the header. You open title, you close title. And you can see how they're nested inside each other as well. That's very common inside HTML. Yeah. Okay, and our lineup is gonna be okay. This'll work. Okay. So anyway, so what I want you to notice here is simply the fact that I built out this full HTML. And HTML at the end of the day is just text. That's really it. And so it is gonna be returned back as HTML, but you know, again, it's just simply text. Still a string. Exactly. And so now what I'm gonna do is I'm going to control F5 here. I'm gonna launch this. And so now you're gonna notice first of all, hello, Susan. I feel special all of a sudden here. All right, now hi. So you'll, yeah, hi. And you're also gonna notice, by the way, that there is Hello World there. Is that what the title tagged in? I'm so glad you asked that. As a matter of fact, that is exactly what that title tagged in. And then you're also gonna notice and you can right click and hit View Source. I always go Alt V, C, which we'll do it, but nobody ever remembers. I did a new shortcut for me. Oh, so there you can actually see the HTML code that we sent back to the browser. Exactly, yeah. Now, obviously we could keep doing this, but we probably... Then it would be an HTML course. Well, I would say two things. That A, yeah, be an HTML course. And actually, slide, slide, slide. There we go. Yeah, if you wanted to get more of an HTML, there's an MVA course on it. Bob Tabor, the HTML5 CSS3 fundamentals. Great course to go check out. You'll also notice the 20480 full five-day course taught by Microsoft certified trainers. And hey, we were both Microsoft certified. We were. We still are. We still are. We still are. So there's lots of material out there to help you get started with HTML5. That's the set. Once you've mastered the Python and Flask components, now that you're seeing how the HTML affects the output, those are some great resources for the next steps. Absolutely. Okay, so what did we learn? Well, we learned how to manage Python environments. Setting up environments, installing the different packages. We learned how to get started using Flask and Python. Yeah, even which project type to use. But it sort of begs the question, well, in the world, can we do with this? Well, for right now, we just built a foundation. So now what we can do is we can use this to begin pursuing deeper knowledge. And you know what? That's exactly what we're going to do after a 10-minute break, because I don't know about you, but I could use a break. I think maybe I need some caffeine. All right. We'll see you guys back here in 10. Okay, well, welcome back to introducing or introduction to creating websites using Python and Flask. Alongside Susan Eyeback, I am Christopher Harrison. And I actually want to go back to one big thing that we pointed out in module one, because there's been a couple of questions about this inside of the Q&A. The people have gone out to GitHub. They downloaded the project. They tried to launch it, and they're going, hey, wait a minute. I got a narrow message. Yes. So let's go in and highlight this. Now, the first thing that I need to stress right away is make sure that you have downloaded and installed the Python tools for Visual Studio. Yep. And that you've installed a Python interpreter. All available at pytools.codeplex.com. Exactly, P-Y-T-O-O, here. P-Y-T-O-O-L-S. I'll put it in the Q&A window as well. Yeah, you know, just do that, because unfortunately my typing on Zoomit seems to sort of come and go. So I'm putting that link right now in the Q&A window. So if you haven't got the Python tools installed or you're not sure where to get the code for the interpreter, it's all on the installation instructions there. Awesome, I love it. Now, this little project right here, you'll notice this is trivia for module five, and if you're just tuning in, we know. It's still module two. The reason that I went with this is because I pulled this down from GitHub this morning. So didn't it already have it on my system? Just pulled it down. And I want you to notice, that's generally speaking, when you say something that looks like this. A little warning symbol? Yeah, that's sort of universal. It means something's not right. Exactly, and so you'll notice that when I go to launch this, I get an error message. And the error message that you're gonna get is gonna vary a little bit depending on what's going on. In my case, it happens to be, system cannot find the path specified. So again, what I need to do is I need to, and let me, there we go, recreate my environment. So I'm just gonna right click on this, and I'm going to say, remove, and we'll go ahead and remove that from the project. Which is a little counterintuitive. You don't think to yourself to leave the thing with the error, but the thing is you're gonna recreate it correctly. Exactly, by just going back in, right click, add virtual environment, and then back over here, it will automatically read from that requirements text file for us. So really all that we have to do is just click create, and then if we just sort of give that a couple moments here, and I'm gonna zoom back out, and again, sip of coffee, I'm almost out of coffee. But yeah, now it's actually gonna recreate the environment correctly with all the packages that are needed for Flask. Yeah, you can actually see all that in the output window behind the scenes, that it's going out and it's pulling everything down. I know it's giving me a lot of warnings, but that's okay, warning, warning. You can also now see, now you can see in the solution explorer, all those nice packages, and we can see the little warning symbol went away. Yep, and we can also see, little control F5, hit yes. No module, oh, hang on, that's, you must have downloaded, that's a finished version. Yeah, you're right. That's, he just tried to run the code, it's gonna work after we're done module five, and we're on module two. Yeah, give me two seconds here. You can just grab that. That's funny. Here, look, it works. Oh, wait a minute. Yeah, you can't jump ahead three chapters without doing the code in between. Yeah. So, but yeah, so absolutely. But the key thing is, but you can see the little warning symbols gone away, as said, and the code will actually run, except we're missing the packages, which we'll be adding this afternoon. There we go. So, there we go. Okay, and so now, now it works. Okay. Okay, see, it does in fact work. There was just one little thing I needed to add in. And in fact, I'm curious if somebody, if that was an error message that somebody was getting. So you know what I'm gonna do real quick here, is I'm just going to check this in. You're gonna update the code on the server. So if anybody else was getting that error about the Redis, if you just download zip file again, we're just gonna update the copy that's in GitHub so that you have the correct version and we don't accidentally give you the code for the later stuff. Exactly, cool. All right, now then. Nothing like being live. Exactly, we're not cutting on this show. All right. Now, I also need to open up the correct project. There we go. And I need to open up my slide deck. And now there was another question that came up in the Q and A as well. Asking about that app.route slash thing. Yeah, we should probably talk about that, shouldn't we? I think so. That might be a nice reminder. We said we would talk about that. So I think it's time. Yeah, okay. Well, let's roll in a model tour then. Okay. Creating web pages. You know, now that we know what a web application is. Yep. How do we actually send information from the user to the server and from the server to the user? Because that is huge. I mean, that's what allows us to really make a web application. It's one, well, we already actually have the ability to just display stuff on a web page to the user. Exactly. But obviously, when I order books online and so on, I can, I go, I ask the server, what books do you have on Python? And it gives me a list and I say, well, I want to order this one. So there must be a way to have two-way communication. Exactly. So here's what we need to get into. Is we need to start talking about how this communication is going to take place. We need to talk about that writing concept. That's gonna go back to that question that you were talking about. And then we need to kind of enable a little bit of additional functionality. But let's, let's, let's start by, you know, talking about how to talk to servers. Now, caution. Caution. Yep. So, so it is a warning, but the cool thing about this is, you'll be able to speak geek so well after this that you are gonna be able to, you know, impress your friends with geek speak once you've mastered this topic. So here's the thing, is stick with me. Yes. I promise you, I'm gonna get you there. It's just gonna take a little bit and there's gonna be a lot of explaining that I'm gonna have to do to get us there. Because there's going to be a couple of very big terms that we need to understand and we need to really understand the why. So this is sort of my spiel. Let me go. I promise you, you gotta trust me on this. I'm gonna get you to the other side. So let's start by defining two big terms here and then digging into them. Okay. And the two main terms here are request and response. Okay. Now request is coming from the user. So the user has made a request to the server. Response is what the server's going to send back. So again, kind of going back to that restaurant analogy, getting hungry. Okay. Coming back to that restaurant analogy, I ask my server, hey, I would like a steak rare. My server is gonna go off, get that and bring that back to me. So I made my request, steak rare. My server is now going to respond by bringing me said steak. So request, this is what I want. And then response is that server sending that information back. Now let's take a look at sort of a real world application, example of this. And let's talk about creating a website. Sure. And in fact, we should probably back this all the way up and ask a question. You know, why are you creating a website in the first place? Well, the reason that you're creating a website in the first place is because you have information that you want to share and because quite likely in some way, shape or form, you want to make money. That is true. I mean, if you think about the websites you visit, they're either trying to show you advertisements so they make money or they're trying to sell us something or service or a product. Okay, so let's break that down. So let's start with number one is advertising. How do we make money with advertising? More visitors. So we wanna make it as easy as possible for people to come to our site, keep seeing the same pages, and we wanna make it very easy for other people to share those pages. So that way when they go to Facebook, they go to Twitter and they say, hey, look, I saw this, this is really cool that they have the very easy build out. So if somebody, when I want somebody to advertise it. Sure. Okay, so advertising. Let's go with number two, services. So I'm trying to sell a service. I'm a law firm. I'm a. A plumber. Plumber. I'm a spackling company. Spackling company. We'll stick with plumber. Okay. So anyway, so what I'd be looking for if I'm a service like that is I want more visitors because after all, the more people that come to my site, that's going to increase the chances that they're going to pick up the phone or fire up an email and hire me for my services. So once again, I wanna make it very easy to allow people to share my site and keep requesting those same pages over and over again. And if we bring this into the last example of, hey, look, we're selling products, which is sort of the one that everybody thinks of the more traditional. Once again, it's still the same concept. I wanna make sure that people have very easy ability to see the page that describes the super widget that I want to sell them. So basically, regardless of the type of web application that you're gonna be creating, the end goal is we want eyeballs, we want visitors. Why? Because if it's our, we want money. That's why we're creating these web pages. So let's take a look then at our little example here and let's say that we're setting up a little photo sharing it. So we've got a little guy here, there's our little photographer enthusiast, see, let's just get a camera. He says, you know, I'd like to download a picture of our koala. So he goes to adventureworks.com slash, and then in this case, sleeping koala. And that's going to send off the little picture of the koala. I, in fact, take that picture. By the way, getting a picture of a sleeping koala is the easiest thing to do. I think they sleep 23 to 23 and a half hours a day, yeah. Yeah, basically, that's their state most of the day. That's a lifestyle that I envy in any event. So they go in and they say, all right, well, this is what I wanna see and the server's gonna go, okay, sure. There's the picture and send that on down. And I wanna get a notice. Something about this URL is that it's nice, it's clean, it's simple, it's replayable. That every single time that somebody types in that URL, they send that request over to the server, you know what they're gonna get? They're gonna get that cute little koala picture right there. Just like every time I say, my favorite restaurant slash menu, it brings me up the menu for my favorite restaurant. That's exactly it. Yeah, really, I know exactly what I'm getting back when I type in that URL. And there's the next big point. You know exactly what you're gonna get back. So you know you're gonna get a menu, I know I'm gonna get a sleeping koala. Because that's exactly what it says. Again, I suppose it's possible we might get Rick rolled in the middle of this, but that's a different conversation. So you'll notice that's exactly what we're gonna get. So having that nice clean URL and having this URL be replayable becomes very important. And as it turns out, when you make a request up to a server, there's two different places that information that you wanna send up could be sent. Okay. So it could be sent in the URL. Right. That's going to be either inside the query string like it is here or it could just be part of the URL itself. So I can actually pass information right there as part of the URL. And that's going to be replayable. So anybody with that URL could access that page. So anybody that sees that URL could access that page. And let's kind of spin this back to my analogy that I've been using is if I'm sitting in a restaurant and I say to my server, maybe some special code. Maybe there was a little discount code. And so whatever it happens to be. So let's just say the discount is web Wednesday. So I say to my server, web Wednesday, and that's gonna get me 10% off. Well, if somebody else over here is me say web Wednesday, you know what's gonna happen? They're gonna be able to say web Wednesday as well and get the exact same discount. And in a lot of cases, that's exactly what I want. That I want that information to be shared. I want that information to be public because if you're gonna offer a discount like that, typically you're doing that to attract more customers to get more people in. And we want that to be replayable. Bringing that back over into our environment here. Again, we want this to be replayable. So every single time that somebody comes in and they say, sleeping koala, we wanna make sure that they can get back that picture. So it's important to be able to send information inside of a URL. Yeah, and earlier you had that query string as well. You do see that a lot of them I find on pages where are online stores. Yes. My husband and I were shopping for lighting fixtures and it was like, hey, I like this lighting fixture and you'd send me a link and it would be a URL just like that, slash, hall lights, query, and it would have that little question mark and then it would have like the catalog number of that particular light. Exactly. And when he sent me that link inside an email, I click on that link and I saw the exact same lighting fixture my husband was talking about. And then we're like, oh yeah, I like that too. And then we can go buy it. Exactly, exactly. We want that to be replayable. We want that to be shareable. That we want more people to come in and look at that. Yeah. Cool. But you know, sometimes there's information that we wouldn't want replayable. So let's kind of go back to my restaurant analogy here and let's say that I start speaking my credit card number out loud to the server. No, I don't really want the person next to me knowing my credit card number. Well, because again, at that point it would become replayable because if that's the way they were going to exchange credit card numbers, the person next to me, here's my credit card number, they start speaking that. And again, that's not a problem. And now you're paying for their dinner. Yeah. Exactly. And we do use credit card numbers on the web. So it's a very relevant analogy. Exactly. So this isn't going to work. So we need some way that we can tuck that information away. Make sure that that's not going to be visible. Now, I'm going to tangent here for 30 seconds. See, you'll notice I slid to the side. That's your tangent? That's a visitor side. Yeah, I'm going to talk over here. One big thing that we're not going to get into today is a thing called SSL, Secure Sockets Layer, which would do encryption. And one big thing that I want to highlight about this header information is that it's not going to be replayable. It's not going to be in the URL, but it's not by default going to be encrypted. Which means if you've got someone who knows how to sneak around and sniff things. You need to move to the side because we're on the tangent mode. Okay, so there's a right? Okay, so yeah. Yeah, to your right. So yeah, so that means these people know how to go hack things and dig around and stuff. They can see the stuff in the header if they know what they're doing. Exactly, yeah. So we would need to use SSL. So this is not going to encrypt it. And so it's just going to tuck it behind the scenes. We still need to encrypt it, but we also still want it out of that URL because we don't want anybody to be able to see that. Okay, back to here. Back to our main program. Yes, we return back to our regular programming. So back over here on that header info, that's again going to be sent behind the scenes, but it's also going to give us one other big advantage here is that there's no size or type restriction. So again, let's say that I happen to be very specific about the order that I want to make. So I'm going to let's say order rib eye and I want that to be rare, but I want that to be- With mushrooms and the teriyaki sauce. Exactly, sliced vertically, you know. Exactly, so I want all of those different things. Well, if I just keep saying this to my server, chances are my server is going to forget this. There's only so much information that you could communicate that way. Sort of the same thing with a URL, depending on the browser and a couple of other things, your URL is going to be restricted on the number of characters. Header information, however, not restricted whatsoever. So we can send a lot more information and it's also going to be tucked away. So let's, you know, I'm actually going to go and tell you I have one of my slides here. Let's actually see this in action and ignore the fact that it says post. I'll come back. Okay. So, you know, here we go with somebody maybe wanting to make a comment here. So let's say they really like that picture. So they'd like to put in a comment. This is not something that I want repliable. That I want to make sure that every time somebody wants to make a comment, they have to go in, fill out the form that they can't to simply grab the URL. So this is where sending it up inside the header information comes into play. So we give them the form, they type in their little thing called cute picture. I really should have stopped that animation over there. But you'll notice they typed in cute picture. Yep. And so now that information is going to be sent up here and I want to highlight the URL. And you'll notice that it's still www.aventureworks.com, whack comment. Yeah, it's true. I'm using the exact same URL, but two different things are happening. The first time I use, I specify the URL, it's just giving me back a blank form. Correct. The second time it's, I'm sending it my filled out form. Exactly, exactly. Yeah. So we're going to get to that first part here in a second, it's that second part that right now is very important because you're going to notice cute picture is not in that URL. So it must be in that header information. There you go. And that is exactly our header information in action there that it's going to be sent behind the scenes. Now let's come back to that first part that Susan just mentioned there. And you'll notice sort of that two step process here. Hey look, I'd like to comment. Well in order for me to comment, what do I need? I need the form to fill out. Exactly. So I punch in, whack comment and it gives me that form back. Right. Okay. And then I go in, I fill out my little cute picture and then we send that back up. So how does it know when to just give me the blank form and when am I sending it a filled out form? Fantastic question. And that's going to be based on two are known as verms, which are get and post. Now, a lot of times when people here get in post they automatically assume, and this is fair, and I got to be honest, I did this as well because it sort of makes sense that when you hear get what you're thinking is I'm getting information, when you hear post you're sending information. And it's not entirely true because I can still send information with a get. When I do get because after all kind of winding all of this back to my little cute koala picture here you're going to notice we sent information. We said we wanted a sleeping koala. And that was a get. Exactly, that was a get. So we can still send information. But the main difference is that we only have the ability to send data inside the URL with post we can do it in the URL as well as in the header. And so remember or it can be URL as well as header. So it could be both. Now the question becomes, well how does the server know? When the browser makes the request it will actually say hey I'm making a get request or it will say hey I'm making a post request and we're going to see in the next module how we can actually control that. How we can actually do either a get or a post. The main thing that I want to mention here is that the default is get. So it's only going to be post if you explicitly do something to send up a post request which is typically going to be done with a form. And again come back to me in the next module and I'll show you how that's going to be done. So as a coder when I'm writing my Python code does that mean I'm going to need to be able to say well hang on if this was a get I just want to send them a blank form and if this was a post then I know I'm getting my information back. 100% correct. That's exactly it. That inside your code you're going to need to be able to detect and that is going to be sort of the typical pattern. Excuse me, typical pattern here is you're going to first detect the fact that they did a get and then what's going to happen is you'll send down the form. Yeah. And then you're going to detect the fact that hey look, they set a post and then you're going to read that data. So that's going to be the typical pattern. And so when we go in and we create for example a create question that's exactly what we're going to have that we're going to have one little block that's just going to send the form down. Uh-huh. There we go. And we're going to create another block that's going to accept that brand new question, save that back into our data store and then send back to the user, hey look, that was successful. So you're going to notice that that's going to be very common programming inside of Flask and inside of your little application. Cool. Yeah. Like I said, bit of terminology. But hopefully what we did there is kind of brought all that together and saw that and I know that chances are after kind of going through all that we need to see it in action and we will, I promise you. But this is one of those things where we needed to find this right up front because when we start getting into things like routing we need to kind of understand that little get post and all of that good stuff. So that's always why I like to cover that. And just to close it all off, the response information, there's an awful lot that could be sent back down with response, could be things like status codes, the type of file that we're going to send that one of the things that we've been highlighting is things like HTML, CSS, JavaScript but we could send down images, we could send down videos. There's a lot that we could actually send down. And so if you are going to send down an image you need to tell the browser, hey, we're about to send down an image otherwise it's not going to be expecting that. You do that inside the header information but typically the content that you're going to be sending down, HTML, CSS, JavaScript. Cool. Now you asked me a question many minutes ago now. Yep, yep. And that question was. We had a question in the Q&A window that asked. A little more, we're trying to remember what that app.route slash was doing inside the code. That's a great question and that is a route. So let's get in and start digging into what routing is all about. Now what I always like to say when it comes to Flask is that at the end of the day, what a user is doing is they're calling a function. Here, let me back out of my slides real quick here. I'm just going to add in an ad hoc demo. There we go. There's my little music for an ad hoc demo. Okay, so you remember this from before. So let's again ignore this right here. What's this again, Susan? That is a purely Python function. That's it, that's all that that is. So what's going to happen here is this function is going to be called. And in fact, here, we can see it. I'm going to put a break point right there. I'm going to hit F5 to go into my bugger. Whoops, and apparently I'm going to hit the number five as well. I'm not sure Python knows what to do with that, so all right. That's okay, neither do I. There we go. Take two here, trigger, trigger, trigger. And you'll notice it decided not to break for me. That was awful nice of you. Did you delete the break point by any chance? No, we'll try again. Yeah, take two. Your code's still running. The number of times we all do that when we're doing demonstrations. It's like, wait, my project is still running. Not enough code inside your function, my friend, to get break points. There's rules about break points, about what types of lines of code they're allowed to be on. So if you declare a variable or something, yes. That'll force it to stop longing us for us to show you that it's running. So this is something, it's just, there's only certain lines of code it'll break on. And now they're going to think we do have some magic code up your sleeve. Stop. There we go. Hooray! All right. Congratulations. Now we can actually get it to break. And you know what's sad is that we spent all of that time for what's going to be a very simplistic demo. I know. But here's the point that I want to make is that we typed in this little forward slash. And if I go back to my browser here and let's just kind of zoom on in here, you'll notice right there at the very end that there's a forward slash. So that is actually what's being sent into Flask, what's being sent into the server. And then behind the scenes, it's now going to run that function. So at the end of the day, all that we're doing here is we're just running Python functions. So what we need is we need a way for our users to communicate to us which function it is that they want to call. Now of course, they're not going to know that they're calling a function. No, they're just typing in some sort of URL. But at the end of the day, they're making a request. They're looking for some behavior. So that when you go to restaurant.com or whatever you're interested in. When I go to my favorite restaurant slash menu, I'm asking for the menu. Exactly. When I say go to restaurant slash directions, I want to see the directions. And when you go sleep in Kuala, you're looking for the sleep in Kuala. So again, in two-part harmony, what you're going to notice is that at the end of the day, we're just making those method calls. That's really, in our users, our requesting functionality. And that is what routing is all about. That routing is all about taking the URL that a user punches in and doing something with it. Now traditionally, in a lot of other technologies, the user, again, not necessarily knowing it, is making a request of a specific page. So they're specifically looking for about us.html, and they're specifically looking for register.aspx. But the problem with that is what happens if later on, we decide that we want to change, that maybe we don't want to use HTML anymore, that maybe we want to use PHP or we want to use MVC. Now that starts to become a real problem. So we want something that's going to get away from calling specific pages and instead request that functionality. And so you'll notice that we've got register, and you'll notice that we've got a bound. Because if I back up here, what you're going to notice is that we've got this little extension here of that .html and that .aspx, I have no idea what that is. Yeah, for the user, that's very confusing. Exactly. And I remember in the old days, it was .htm, and somewhere .html, and somewhere .htm, and it was .asp, and then it was .aspx. It got really confusing for the poor users. Yeah, exactly. But if I say whack about or register, I know exactly what's about to happen on the other side. I'm going to bring up the about page. And do I care what's happening behind the scenes on the server? I certainly don't care if you did an ASP versus ASP.net versus HTML, I just want to get to my web page. I just want that functionality. That's exactly it. So it's going to create more readable URLs. It's going to give us increased functionality or flexibility. And then most importantly, it's going to give us search engine optimization. And we could spend the entire day talking about SEO or search engine optimization and probably barely scratch the surface. Yeah, which is all about trying to show up on the first page when they do a search. Exactly. And here's the thing, is if you just follow a couple of very simple little steps, you're going to be just fine. That you're going to be able to show the search engine what your site is all about. And one of the simplest to highlight is the fact that your URLs are very simplistic. That when I go to WAC register, I know what's going to happen. When I go to WAC about, I know what's going to happen. And not only do I know, you know. The search engine knows. And the search engine knows. And that means more people find you. That means more people visiting your site, which means you make more money with your advertising, your restaurant, or whatever you're doing. Show me the money. Yes. By the way, last little thing to mention here is that there is an MVA on search engine optimization. Why am I not surprised? I couldn't save the coverage at this point on MVA. It's pretty amazing. Hey, yeah? Yeah. All right. But back to our routing. Back to our routing. So what I want you to notice is, routing is taking that URL and translating it into something. So the server needs to understand what in the world the user is requesting. So the server doesn't know what WAC register is. You're going to tell what it is by adding in those routes. And that's going to be where you specify the URL for that particular desired item or function. So let's go in and take a look at kind of routing 101 here. That if I go into Visual Studio, and let's just come down over to here, is I'm going to say app route. OK. So you're adding another route now. So right now we had the slash did our hello world. So you're now adding a new route. That's exactly what I'm doing. OK. So I'm going to start with the forward slash. OK. Start from the root of our server. And then I could type in really whatever word it is that I want here. So could I use Wibble? Yeah, well, a user wouldn't really know what the heck Wibble's doing, but OK. Shove two pencils up your nose. Put your underwear on your head. Keep saying Wibble over and over and over again. And it helps you get out of the army. If you say so. True story. So in any event, could I say Wibble? Absolutely. Wibble, Wibble, Wibble. But it doesn't actually mean anything to the outside world. So I want this to be nice, clear, and clean. So instead, what I'm going to do is I'm going to say create. Because what this is going to do is this is now going to create a question. Right. Because this is the first step towards a trivia app that you are not planning to build. It is. Yeah, I'm going to build like a little bit of it now just so that way we can use these demos later. Don't worry we are going to get into the specifics of it. But right now, yeah, create. Yeah, this is going to be the starting point. Now, so we just added that in. So what we've now said is, hey server, if you see somebody type in create, what I want you to do is I want you to call the method that's going to be right under it. That's all that happened right here. You'll notice that that was the method that was called line position, location, location, location. It was right under that app route. So I now come back over here. And I'm just going to define. A new Python function. A new Python. And I'm going to call it create. And that is really a good practice. Just call it the same thing as the route. And that way it'll be easier for you to remember. It doesn't matter. You could have called it Wibble. But it's just easier for you to follow your own code if you use the same names for your functions as you do for your routes. Exactly. Now, I am going to cheat a little bit here in that I'm just going to send down an H2 tag. I'm not going to build out the full text that we saw up above. And the reason that I'm not going to do that is just because we're going to go back and throw that out. We just want to show that this route calls this function, right? Exactly. That's it. That's all that we want to do. And so, sure enough, you're going to notice that if I go in and I now say create, there is our create page. So you'll notice right up at the very top, I said create. And it's now on the create page. Perfect. So a different route, different functions call, different output displayed to the user. That's exactly it. Now, let's, let me close that out. And I'm just going to close all of that out. There we go. Now, one of the things that can happen here is that your application can get very big. Oh, yeah. And so it's very possible that you're going to have dozens, maybe even hundreds of different routes out there. And so, you know, it's going to get a little bit tedious to try and keep everything inside of one file. To get very cluttered. Yeah. So fortunately, we can create additional files. So let's actually just add in, add, new item, empty Python file. And I'm going to call this routes, which is where our routes will be stored. I like that. Nice and easy. And what I'm going to do is I'm going to cut my code here. So you're taking the code out of the app.py file, of a routing code, and moving it to the routes.py file. Exactly. So I just simply move that into my routes. And I'm also going to serverwack create. Let's, you know, add some comments. Good idea. And so this demo is not going to work. You're going to notice that I've moved that code over. So it's the same code that we saw before. And I run my app, and you're going to notice that I'm going to get a 404. File not found. And you're probably wondering, well, wait a minute. Why was that not found? That's a good question. The reason that it wasn't found is because my application doesn't know to actually go call that routes file. So what I need to do is I need to go import. Well, that kind of makes sense. It's not just going to magically just go searching for, are there any files out there somewhere that have the routes defined. You have to tell it. It'd be nice if it was magic. There is no magic in Python. So what I need to do is import that. So I'm just simply going to say from routes, import, and then asterisk, which means import everything. Now, by the way, there is no magic to the name routes that it's just simply routes. Well, it is convention. Again, could I have called it WebL? Sure, but nobody's going to know what that means. I mean, if I opened up somebody's project and I saw a file called routes, I might guess, but that's where they're doing the routing. And that's why you're doing it. And you might also decide, as your project gets bigger, that you're going to create additional routes files as well. So you would just simply import all of your additional ones. So maybe for our cart, we would say import asterisk. And maybe from our products, we would say import asterisk if we were creating an e-commerce site. So we've got all those different files. So we just simply import all of them in and away we go. So now, let's go ahead and launch this again. It's going to fail again. Yep. And now you're going to notice I'm getting a slightly different error message here. Yeah, it's actually coming back saying app is not fine. That's true. And you did have code and there's this app.route. So it looks like it can't figure out what app is. You're absolutely right. It can't figure out what app is. So what I need to do is I need inside my routes pie is I need to pull in two things. First of all, we're going to be doing flask in here, right? Yeah, well, yeah, absolutely. We're doing flask. Guess what we need? Maybe need to import flask. Hey. So we need that. And then we also need app. So I'm going to say from app import app, which I know sort of a little bit of a funny line from app import app. Here's what's happening is let me do this this way. App here, this is the file. So that's pointing to our app pie file over there. OK. App is the name of the variable that we declared. So if I come back over here, there is the variable that I had declared. Right. So that's the app variable it was saying it couldn't find. Exactly. So now we've got flask. Now we've got app. And now we run this one last time. Chugga, chugga, chugga. And there is our hello world, Susan. Let's go in and say create, and there's our create page. So now we have a nice, tidy way of sort of not cluttering up one file with everything, because that can get unmanageable very fast when you start building bigger sets. Yeah, exactly, exactly. So yeah, absolutely. So just cut and paste for routing information into a route.py file. You can call it something else if you want. But routes is nice, easy to guess name, intuitive name. But you do have to add a couple of import statements to the top of the file. There you go. All right. Cool. Now, let's keep on keeping on, shall we? Yeah. Because up until now, all that we've done is just showing off the ability to do this part of the URL. Right. Now, it'd be nice to be able to take a variable right over there instead of that question mark ID equals blah, blah, blah. No of those query strings. They call the query strings. Yeah. Exactly. And we want to make sure that this is going to be nice and clean and easy, so that if I go to www.example.com, waxspeakers, wax, Susan Eibach, guess what I'm going to see there? Christopher Harrison. Close. I figured you'd hack my website, gone in there. Not quite. Now, what I'm going to see there is I'm going to see information about a speaker named Susan Eibach. And it's all right there in the URL. And sometimes this is what's known as a vanity URL, because the name of whatever it is we're going to see on the other side is inside of that URL. And why is this important? Well, once again, it's important for search engine optimization for SEO, because that's Susan Eibach. So the search engine is going to know that that's Susan Eibach. On top of that, it's once again going to give us predictable URLs. So if somebody hands me that, www.example.com, waxspeakers, wax, Susan Eibach, and I know that, for example, maybe Christopher didn't speak there, that I could go in and I could say, wax Christopher Harrison. And hopefully it just, I guessed. Exactly. And I bring up the speaker information on Christopher. That's it. And so now what we need to do is talk about how we're going to add in those vanity URLs. So once again, let's come back over here and let's just go in and say server, wax, question. OK. We're on that later. And then I'm going to use an angle bracket title angle bracket. OK. Now, angle bracket, something angle bracket is traditionally. It's traditionally used to be a placeholder, right? Yep. OK. How about that? Route, question, title. OK. It's traditionally used to placeholder. OK. Guess what? It's a placeholder. So here's what's cool is that it's automatically going to be looking for some bit of string afterwards that's going to be title. And I would also mention real quickly here that if you wanted to constrain that, that maybe you just wanted that to be an integer or you wanted to force that to be a string or something like that, that you could go in and do that. So yeah, if you're expecting an ID number, an account number, you can specify. Yeah, I think you could say int colon. Yeah. So in my case, I'm just going to say title. And then I'm going to say def question. And I'm going to say title. Oh, so you're just accepting as a parameter to function, just like we would with any Python function. We want to accept parameters. That's it. And I'm going to say return. And let's go in and say h2. And I'm going to say plus. And I'm going to say title. And I'm going to close out my h2 there. By the way, something I just picked up on here. And this is, it's one of those things. Sometimes Python is a little bit too flexible. And so you wind up easing into bad habits. And I've sort of eased into that. That you might notice here, and I apologize if I've confused anybody, you might notice that I've been using single quotes on the route. And I've been using double quotes here. And that unfortunately, it's just been sort of the way it's been flowing off my fingers. I could absolutely use single quotes across the board. And I could absolutely use double quotes across the board. So I'm just sort of a bad flow I got myself into. Now, in any event, let's go in and highlight something here. You are going to notice that once again, Susan, I'm going to put you on the spot. OK. The spot highlighted in blue, that's a. That is just a Python function. There you go. The difference between this one and the others is this one's accepting a parameter title, which means the function's expecting me to pass in a title when I call it. Cool. So it's expecting title. So it's expecting a parameter, still just a normal Python function, but expecting a parameter. Guess where it's going to get it from? I'm hoping it's going to get it from that URL. Do I have to do anything to magically connect that, save it that title placeholder? I want to put it into that title parameter? Just make sure that the names are the same. That's all you have to do. So if you say title, say title. If you say Wibble, say Wibble. So you just have to make sure that those two are the same. That's it. Cool. And so now, if I, once again, launch my little page here and I go question Wibble, it's going to print out Wibble. And if I say question Christopher, it's going to print out Christopher. So it's just taking that title, passing that in, and then giving me access to that. That's pretty cool, right? Yeah. That is neat. So I actually, yeah, can actually read a string or something that they typed into the URL. And then in my code, I can use that string. That's going to be pretty powerful. That's exactly it. Yeah, it's very powerful. We'll actually see later on how we're going to be able to use this to go load our questions for our little trivia app. OK. Now, back to our slides here, because we've got, go away. Too many things open at the same time. There we go. My taskbar just didn't want to behave. One of the little problems that we can run into here is that we need to be able to create links. And so in order to create a link, we need to have the URL. And unfortunately, the URL might change. That's true. And it might change for restructuring purposes or otherwise. So if it changes, and I've hard coded that URL in 12 different places, I don't have to run around all of those 12 places and change that. Yeah, and that is true of coding a lot of times. What drives you nuts is it's that old rule of as soon as you find yourself copying and pasting the same line of code to 10 places, you're thinking, oh, it's easy. Just cut and paste. Yeah, it's easy until one day that thing you cut and pasted changes, and now you have to remember change it in 12 places. Exactly. So there's an old phrase that's sort of streamlined as Einstein once said, don't memorize anything. You can look up. And the full story behind that is he was doing an interview and some constant had come up. And Einstein didn't know what it was. And the reporter was flabbergasted at this. How could you not know what this is? And I said, why would I memorize something that I could look up in a book in under two minutes? My corollary to that in programming is don't hard code anything that you can look up. So if I can ask for that value, I'm going to ask for that value rather than hard coding that in because once again, that could change. So let's take this and take a look at how we can add in a link here. So once again, back over here to our little page. And on the home, instead of saying, hello, Susan, sorry, Susan, I want to now create a link into the create page. Oh, awesome. Because we see web pages doing that all the time. You have forever, you know, you land on the page and said, I'm going to go back to my restaurant. And, you know, on the main home page, there's if you don't know, you can type restaurant slash menu to get to the menu. Then usually there's a little link on the page where you can click and say, take me to the menu, take me to directions, let me make reservations. Exactly. OK. So that was like a perfect level of distraction here. I try. And I need as we have the code here, my quotes. But yeah, there we go. OK. So what I'm going to do here is I'm going to set up my little create link. And I'm just going to add that in. So create link is just a variable that contains a string. That's it. And that a href, that's the syntax of HTML for providing a link to another page. Exactly. But what I need inside of there is said link. Which would be some sort of URL, www.something or ATPP something. Yep. So I want to point that at create. OK. So as long as the function name doesn't change. OK. So you've got to keep that. Because something's got to be consistent here. So as long as the function name doesn't change, you can go ahead and keep doing it. And so all that you need is this little thing called URL4. And then in my case, it's going to be create, right? No. Well, you're going to notice that if I fire this up, it would not work. The reason is that it's not going to know what URL4 is, well, 4. It doesn't know what URL4 is. OK. So I need to go import that in. And you're going to notice that that's inside a flash. So I go in and I say, aha, URL4, let's bring that in. And that's now going to bring that to life. And so now you'll actually notice that if I go in and I say URL4, open parent, now it's actually giving me the IntelliSense. So now I could go in and say create just like that. OK. There we go. And now let's go back in. Let's say yes. Let's check it, check it, check it. And now you're going to notice it says create a question. And I put my mouse over this. And down at the very bottom, you're going to notice that it now says create. And just to sort of prove a point here, there we go. If I updated that route to say Wibble, Wibble's always just my throwaway word. And it's also a reference to a BBC show that nobody knows. What I want you to notice is this. Is the function that I had created. I don't know why my typing keeps disappearing. The function that I had created, I had said define create. So you just renamed the route. You didn't change the function name. Exactly. Just renamed the route, didn't change the function name. So as long as that stays the same, that's just going to make a mess of things. It's still going to make a mess of things. There we go. As long as that stays the same, it will always pick up what the route is. So you'll notice that it automatically updated itself to now be Wibble. Awesome. So that means I can change the URL that a user wants. If I want to rename or I'm making a French version of the website or something. So I want to change it to, well, I guess, menu, still menu in French. But create instead of create, then I have that ability. And now that route points to that same, points to that function. And I don't have to change my code. Just because I changed the URL, people type in to get there. And that's exactly it. That's exactly it. By the way, Barry, our camera guy in the back, asked a question, is Wibble from Blackadder? And the answer to that question is yes, it is. Thank you for getting my reference. Cool. All right. You're not alone. Fantastic show, by the way. In any event, let's close all this off. Because we covered a fair amount of ground there. And so the question then becomes, well, what do we learn? Well, we learned about, get them post. We learned how to create custom URLs. We learned how to send information to the user. We are going to see in the next module how we can pull that information in. Well, what can we do with all of this? Because that seemed sort of esoteric. That seemed kind of academic. Well, the biggest thing is, isn't we now learn how to best share information with the world? That you want to keep your URLs predictable, nice, clean. Make sure that the user understands exactly what they're going to get when they click on your link. And in turn, the search engine is going to get. We also saw how to create our custom URLs. And we also saw how to go in and begin building our own web applications. But of course, we need to keep going. Absolutely. There's more to do here. But I need a break. I bet you're not the only one. Let's go ahead, take 10 minutes. And we'll come on back. We'll see you in 10. All right, well, welcome back to our Jumpstart on Introduction to Creating Websites, using Python and Flask alongside Susan Iback. I am Christopher Harrison. Now, we have been taking a look at really kind of the basics of everything about how to handle our routing, about HTML, how to send information down. And I think now it's time to kind of bring all together. And let's start building a bigger app. Now, before I get into that, I do want to mention real quickly for everybody that is watching this live about the couple of little streaming issues. Yeah, there was a couple of things that's morning. Yeah. So one big thing to keep in mind is that this MBA will be available about two weeks from today. Today is Wednesday, the 17th. So yeah, so you can check that out in a couple of weeks if you did wind up missing some really bad jokes from the first module. And there is incentive right here. You'll wash on them. All right. So our big purple slide here or my big purple slide, we could keep building all of our little files to just send text down to our users. We could. Yeah, because at this point, we have the ability to have multiple webpages to move between those different webpages. So we have that ability. That's a start. By the way, that is the oddest sentence I think I've ever written. Who did the editing on this in the event? By the way, that would be me. Happy you, yeah. I really need a better editor. In that event, we could keep doing that, but that isn't going to make it very easy to create a rich UI. I mean, here, let me actually bail out of the slides for a second, and let's fire back up Visual Studio here. I mean, look at this. That's a pretty clunky line of code if you're going to have to do that every time you want to display something nicely on the screen. And when I was having that out, one of the things that you had mentioned was that you were going to get a high five if I did that without typos, which by the way, you would be high five. Oh, high five. This is true. Yeah, oh, you can go high five. You managed it. Oh, here we go. See, there we go. Captured. Well done. Thank you. So yeah, so we could do that, but that's going to get really old really fast. And on top of that, there's a very good chance that you're going to have a division of labor between your web designers and your web programmers, that if you're anything like me and I know I am, I'm good at the, I pull out that line every MVA. If you're anything like me and I know I am, I'm very much a back of the house kind of guy. I can do all the programming on the back end. But if you're looking for something that's going to look very pretty, I need a lot of help. It's really not my skill, but there are people that have that skill. And I want to make it easy for them to do their thing, make it easy for me to do my thing, and then we'll bring it all together and we'll have a very good looking app at the end. Yep, makes sense. Yeah. So let me go ahead and bring all this up. So in order to do this, in order to build the application that we're going to want, we're going to need forms. So we need to talk about how to allow our little user, there's my little user dude, and my user to send information up to the server. That's going to be with a form. So we need to figure that out. We also need to figure out how we're going to build better HTML. That's going to be our Jinja templates. And then finally, last but not least, we're going to build the structure of our app, that front end, and then you're going to come along and you're going to take care of the app. I can do a little more back and a little more logic to the back end. Perfect. OK, so let's talk about forms. What is a form? Well, a form is all about collecting information, sending it up, and then eventually we're going to need to read that. So let's start by talking about how we're going to collect information from the user. And the way that we're going to do this is by setting up input controls. And this is an HTML, one of the HTML controls we can use on our web pages. Exactly. And it's worth highlighting that there's dozens of these. That there's options for dropdown lists, there's checkboxes, there's radio buttons. And you could also, with a bit of JavaScript magic, create your own. But we're trying to keep this a little bit simpler that our main focus is on Python and on Flask and not on HTML. So we're just going to keep it real simple with our basic input controls. But I do want to highlight once again, there's MVAs where you could learn all of this if you wanted to dig deeper. Now the first main attribute to highlight is name. And this name is important because that's the name that's going to get sent up to the server. So you need to make sure that the name in your HTML form is going to match what you're going to be reading on the server. So name becomes important. And then you're going to notice right here the different options for type. And so we've got text, which is going to give us a text box. We've got password, which would give us asterisks or little dots for the letters that we type in so that way we don't see what the password is. Again, I'm going to go back to my tangent. Let's go back to tangent mode again. There we go. One big thing to keep in mind is that even though we say type equals password, it does not encrypt the text. So it just hides it on the display, on the browser. But it doesn't encrypt it when it's sent from the client to the server. You're going to need SSL again to do that. So it just protects you from somebody looking over your shoulder watching you type in your password. Exactly. Exactly. You need to get in tangent mode. Sorry. Other way. Other way. I can't get a. It's like forward slash, it's a backslash. I can't keep it straight. OK. So anyway, it's only going to put the little dots on there. The last one to mention is email. And this is one that I always get asked when I'm doing different web classes, is how do I get on a touch keyboard the at and the dot com to automatically appear on a text box when I'm asking somebody for their email address? And the answer is type equals email. And it's worth highlighting that that is a new HTML5. Yes. Right. So if you're running a really old browser, it might not work, but most browsers these days support that. Well, yeah, it wouldn't work on the touch keyboard. It's not going to bring that up. But one very cool thing is, once again, you could actually do input type equals wibble. And what it's going to display is a text box that, again, remember, we talked about the sort of the best attempt that the browser is going to do. If it sees type equals and it doesn't see something that it recognizes, it's going to go, well, it's probably a text box. I'm just going to give you a text box and just go with that. So it's just not going to put in the rest. So it'll still function, but it's not going to give you the cool little ad and the .com on that. Now, the next part is we've given you the UI to type in information. How do we get that information up to the server? We're actually going to need two things. We're going to need a submit button. And I don't have a slide on the submit button because it's going to be button type equals submit. I'll show you in a minute. But we also need to determine how we're going to send that up. And if you remember, it was get by default. So it's always going to be get by default. So when we typed in our URL, forward slash, or forward slash create, or forward slash question, it was just simply get by default. If we wanted to be post, so we want to be able to send information in the header, then what we need to do on our form, so you'll notice form and all of our input controls go inside of there, then what we need is method equals post. Now we could say method equals get and send that up. And you'll notice, for example, if you fire up bing, and you type something in that will appear inside the URL, the reason is that they said method equals get because once again, they want to make it repliable. So you could actually take a bing search result page, copy the URL, paste that in, and it will work because it uses method equals get, puts all that into the URL. Again, post is going to send that into the header. The other thing is the action parameter, and you'll notice that I don't have an action parameter in here. Nope. And the reason for that is because by default, it's going to go back to the same page. And I put that in quotes, just kind of use that kind of loosely, that if you remember, we want the ability to do create, for example. And we talked in module two about that two-step process that step one is going to be sending the user the form. The blank form to fill out. Exactly. And then step two is going to be sending that up. And we just wanted to go right back to that exact same spot because remember, again, we're going to have those two blocks of code. This is going to be get. This is going to be post. So we're just going to put all of that right inside of that one spot. OK, so let's. I'm going to clear my screen because I've got a lot of phone. So if I had a website, one of these ones where I'm ordering books or something, a lot of times on those, when you finish typing in your order and you sort of hit submit, it then takes you to enter your billing information. And then when you submit that, it takes you to shipping information. That's when those actions become important? Sort of. So the action, well, yes, actually, because if it was going to go to a different page, one of the ways to handle that would be to have different actions. So you might have one action that's going to say enter address. So I'm going to have something called address. And then I've got another one here that's maybe going to be a credit card. And then I've got another one that's going to be confirmed, or whatever it is that it happens to be. One of the ways that you can handle that is by using different actions. So if you wanted to send to somewhere else. So after you submit, give me this page, then I'm going to send you to the next page, action is one of the ways you can do that. Exactly. Yep. OK. But in this case, we're going to be a little trivia app. We're going to stay on the same page. Exactly. Exactly. Then the last step, so we figured out how we're going to collect the info. Figured out how we're going to send it up. The last step then becomes how we're going to read that information. And what you're going to notice is that there's a request form collection where it's going to look for the names on the input controls, match them up, and give me the ability to pull those in. So that's how in my Python code I can say, tell me what they typed into that form. Exactly. Exactly. And that's what we're going to be doing. So you'll notice here, input type equals text, name equals answer. Inside of my Python, it's going to be name equals. So we just declare a variable here, and then request form, answer. And you'll notice answer. And those have to match. Because I'll tell you the number of times I've made typing mistakes between those two, and said, why am I not getting a value in my Python code? And I'm like, oh, wait, never mind. I have a typing mistake between the two variable names. I have a great memory. It's just really short. And so the number of times where I'll put in something over here, and then I go into the Python code, and I just completely forget what it is that I've done, I really do recommend either one of two things that either, A, you just do them both in tangent. So I go in, create my little bit of code, and then immediately create the form, or, B, that I go in and I simply fire up two browser windows so that way I can see them both side by side. Yeah, have the code editor windows side by side. That's why you want two monitors. By the way, if you haven't done it yet, as you get into coding one day, you're going to want dual monitors. Oh, every developer, when I take over the world, which will happen, every developer is going to have dual monitors, if not three. I have three at my desk, and I cannot imagine living without it. Every developer needs dual monitors. OK, let's go in and create a form here. And this is going to be sort of a little bit of, trust me, we're going to get you there. But I am going to sort of do this in steps. So I'm just going to create a new folder here that I'm going to call templates. We'll talk about why in a minute. And I'm going to create a brand new form here. So I'm going to say add, and I'm going to say new item. And this is going to be create a question. There we go. And whoops, I did that as a pie file. I didn't think you wanted a Python file, sorry. Yeah, yeah, yeah. You know the number of mistakes you make is always directly proportional to the number of people watching you. Yeah, you notice the moment I had a blank file, I'm like, wait a minute, it's supposed to be HTML. I don't want to type this in. Create a question. All right, so you're basically creating an HTML file, which is something that you could. OK. Yeah. So just create a new question. And then I'm going to go ahead and say, let's say H2. Please create a new question. And then I'm going to create my little form. And I'm going to say method equals post. And you are going to notice, by the way, the IntelliSense does show me other verbs, delete, put. There's also a couple of others. The only two that we're interested in today are getting post, so post, which again, is going to send it in the header info. And then I'm going to go ahead and say div. And I'm going to, I'm actually going to get a little fancy here, because I'm just feeling like it. So I'm just going to say for equals title. And I'm going to say title. And what that little label is going to do is it's going to look for an input control with a name that matches, so you'll notice name equals title. And so if you click on title, the text title, it will automatically put the focus or put your cursor into that text box. And that's one of those little things that you should get into the habit of, because it makes it more usable with touch. Because then I can touch not only the text box, but the text as well. And these days with mobile devices and tablets, you're going to have a lot of people using your website on touch devices. So it's something, yeah, build up good touch habits early. Exactly. Yep. Yeah, really just designed for touch first. Now I am going to sort of be a little bit lazy here. And so this is going to be for the question and question and question. So basically what you're creating is a text box, which Yeah, you talk, I'll type. Yeah, exactly. So we've got a text box to display where somebody can enter a title to sort of and specify a category for the type of question they're going to do for a trivia app. We're creating a text box where they can type in a question that they can quiz somebody with and somewhere where they can type the correct answer. Because our goal, the final app we're going to actually be building today, it's a little trivia application where you can submit trivia questions and then people can try to answer the different trivia questions. That's exactly it. And each trivia question has a title, it has a question, and it has an answer. There it is. And so that's exactly the form that I have just created right here. Now let's create one other one real quick here. So I'm just going to go in and I'm going to say add new item. And we're going to go to the other side here. And let's go ahead and call this answer question. OK, so this is going to be the form which someone's going to use to answer a question or to be, is this going to be the one where they will be prompted with a question and they type in an answer? That's correct. OK, right. So on this page basically we're going to need to display the question that they have to answer. And we're going to need some sort of text box where they can type in the actual answer to the question that they're prompted with. That's exactly it. Keep talking. Keep talking. All right. And you can see that once again we need a form because when we want to send the results back to the server we're going to need to have a form to do that. And of course we post the completed form back to the server. And that's going to allow our Python code when it receives the form back to actually find out what they typed in as an answer. Because we're going to have to write Python code to see if they typed in the right answer or the wrong answer. And then react to that. There it is. OK, so just like Susan said, so we're creating two different forms here. This is where you're going to be able to upload questions. Now I know we haven't seen the form yet. And we'll go in and see that in a second. Actually, you know what I'm going to do. I'm going to do it this way. Watch this. I just created a basic HTML. So let me actually just go into here in trivia MVA, trivia MVA templates. So there's my basic HTML file. So let me just right click open with internet explorer. And sure enough, there is that little form that we just created. And if I hit submit answer, that would then upload it. And then the exact same thing would hold true here is if I say open with and internet explorer, you'll notice again that there is the one for creating the new question. Right, because as we said, HTML is a language that the browsers understand. So you don't once you've got it. So all we've literally done here is that here's an HTML page. You could just ask a browser display that HTML page. But then when they press submit button, there's no it doesn't know what Python code to call. That's where all this flask stuff comes in. And that's why the HTML is part of our bigger application. Exactly. Yeah, so that's what we need now. Susan mentioned a big point here, that this is going to eventually display, hey, enter the correct text for the question. You know what I need right here? I need the question. Yes, this is true. Somehow we have to, because you're right, somehow Python has to have a way of saying, here's the question to display to the user, and then we can check if they have the right answer. Yep, cool. Well, guess what? We got a technology for that. I'm glad to hear it. Otherwise we'd be in trouble. We've got Jinja. So what is Jinja? Well, I'm glad you asked. It's like a ninja template. Yes. I just love the names in this flask Python. I'm just having too much fun with the names. Oh, absolutely. Yeah, you're going to have fun with the names. So Jinja is a template language. And it, in a nutshell, gives you the ability to inject code into HTML. And that's actually why I just jumped right ahead and I just created the template folder, created a couple of HTML files, because those are basic HTML. And I am going to be able to inject my own code into there just by using Jinja. So for example, if I wanted a bit of code to detect whether or not the person was right and display congratulations, you're right, or maybe I want to go in and display, sorry, you didn't get the question right, then I can go in and do that. But here's the thing, of course. If I say sorry, you didn't get the question right, sorry. Then we're going to need to be able to display what they answered, and what the correct answer is. So I need a way, placeholders, yeah. So I need a way so that my Python code needs a way of saying, hey, when you display that HTML back to the user, can we pass some values back to display on that page? That's exactly it. That is exactly it. And so that's what Jinja allows me to do. So these templates are just HTML, nothing fancy, and they're going to be inside of a folder, wait for it, called templates. So you're putting the routes into a file called routes.py, and now you're storing templates in a folder called templates. I try to keep things as confusing as possible. Yeah, yeah. Yeah, that's it. Now, one of the interesting things is that Jinja does have a code syntax. So if you want to inject if statements and for loops and so forth into Jinja, you can, and you are going to notice that it's similar to Python, but it's not Python. Justin, just close enough to confuse you. Yeah, something like that. That if all I want is placeholders, then I can do that very easily just by using double curly. So double curly placeholder will automatically display those variables in that spot. The question is, well, how are those variables going to be set? Well, as it turns out, there's a brand new method that we're going to have called vendor template. So we call this, this is Python code, this method up here. This is Python code up top. This is the name of the template, so it's automatically going to look inside of that little templates folder for something in my case called template HTML. OK. Server abbreviating there. There we go. And it's also, in my case, going to pass in two parameters called name and called. So now when I'm saying display that page, I have a way of saying, hey, I want this name to go here. I want this value to go here. That's exactly it. That's exactly it. And you can also get in and add logic as well. So if you did want to do an if statement, you could do an if statement. If you wanted to do a for statement, which is the first demo that I had on this slide, you can do that as well. Now here's the catch is the way that control blocks work. So for loops and if statements, the way that they work is based on tabs, based on positioning. Doesn't really work in HTML because my positioning is going to change really depending on my HTML that I want to be able to format my HTML and just have a little bit of code there. So the tabbing isn't always going to come out quite the way that I'm going to want it when I'm dealing with both HTML as well as code. So as a result, we need to get a little bit more explicit here that you're going to notice that we've got end4 to end our for block. And you'll notice that we've got endif to end our if block. Now I also want to highlight the little correct there and my little names here. And those, in my case, are simulating parameters that would be passed in again by using that little render template. So if you gave me a collection of names to display, then I could display all of those. And if you give me a Boolean value, then I can react to that. Now earlier on this morning, one of the big things that we talked about was the concept of Python Flask and it being a stepping stone for other technologies. So that maybe you want to use this and you want to go off and learn Node or you want to learn PHP or you want to learn something near and dear to my heart, MVC. There's an MVA for that. If you want to go off and learn those technologies, a lot of what you're learning today is going to be applicable to there. So let's take MVC, for example. MVC has what are known as views. Views in Flask terms are templates. That what they're designed to do is to display our data. So these ginger templates we're creating are kind of like views in MVC. That's exactly it. That's exactly it. And so as a result, since, again, we're just learning this, we should really start to get into some best practices here. Yes, good to pick up good habits right off the top. Absolutely, absolutely. And so as a result, what we want to do is when we're talking about a view, is keep it a view. That there's this little concept of model view controller where our model is our data, our view is how we're going to see it, and then the controller is going to be kind of working a little bit behind the scenes to take a model, combine it with a view, and send it out the door. Our view should basically be dumb. It should not know about what's going on behind the scenes. It should simply take some data and display it. Right, it shouldn't have business rules, but say things like, oh, if the answer was correct, then I want to do this. If the answer is wrong, I do something else. That's starting to get to the logic of how your program works. And yeah, you don't generally put that inside views. Exactly, yeah. So they really shouldn't contain a whole lot of logic. So let the route method that you've been using determine which view to load, and then create different views for different outputs. Because if we wanted to really keep digging into this and start creating a lot of error handling and things like that, we're going to want a view to display an error message. And we're going to want a view to display, this was correct, and this was incorrect, and this is how we're going to ask you for the answer to the question. Because that, in the long run, is going to make things that much more flexible. Because I get to focus then my attention on how do I want this to be displayed? And how do I want this to be displayed? Rather than injecting a whole bunch of code, because when you start to do that, it's just going to get confusing after a little while. And by the way, while we're talking about a little route methods, it's also not a bad idea to even start creating separate Python files for all of that complex logic, or maybe create classes, classes. You know, we should talk about creating other MVA on creating classes. Yeah, yeah, yeah, yeah. Let's talk later. Absolutely, sounds good. Yeah, all right, in any event, let's sidestep a little bit here and talk about how we're going to bring all of this together into building our app. So the app that we want is a basic trivia game. So we want to be able to do two things. We want to be able to add questions and answer questions. That's what we want. Now, if you want homework, later on, you can add on additional functionality. Maybe the ability to delete questions. Maybe the ability to modify questions. So this is going to be kind of our basics. So we want to add questions. We want to answer them. If you want to keep building on from there, you could keep building on from there. So what are we going to need for this? Well, we're going to need the ability to add our questions. So we need a page with a form to add a question. Hey, we've got that already. We need a page to say it was saved. Okay, well, we're going to have to create that yet. Yeah, we don't have that yet. And then we need somewhere to save the question. And that's coming up. That's coming up. The next module. That's when I get to dominate the conversation a little. You get to write code. And I'm just going to lean back, play on my phone. In any event, the next little thing right here is you're going to notice that we also need the ability to answer questions. So we need a page with a form. We've got that. We need a page to say you're correct. We need that. And we need a page to say that you're wrong. And again, we need that. And we need somewhere to save that question. And again, that's going to be Susan. And so these two items, we're going to see after our break, these three items and the logic to make all of that happen, we're going to see that here in just a couple of moments. But just to put out the big picture there, our moving parts, there's our route py file. We've got our create and our question title. And that was what, route.py was what controlled when someone types in a ticket URL, which pages and so on are being displayed. That's exactly it. We've got those two little methods. We created those earlier. And now we're going to link those up to templates. So we're going to have our create question and create to add question. Probably not the best name, but. That'll work. It'll work. And then we're also going to need for the question side, a form for answer question, and then a correct and an incorrect. So those are going to be the moving parts. This already done. This already done. I need to create this. I need to create this. I need to create this. And I need to update those two. Guess what I'm about to do? That's quite the two to us. Okay, so wait a second. So basically we have a few new web pages we're going to need to create. And we need to make sure we've updated our code so that when the templates are expecting values that we're passing in the correct values to them. Exactly. That's exactly it. Okay, I think I can keep up with that. Cool. I'm going to start by creating the HTML just because that's sort of the easier side. And then I'm going to go back and take a look at the code. So that way we've kind of got that nice clean separation. And I am going to come back to the slide a couple of times just so we can kind of keep seeing all of that as we move forward. But let's go in, fire up visual studio here. And let's start off by updating our answer question here. So again, we needed to add in our question. Yep. Right. So now you're using that ginger syntax to specify that when this page is displayed I'm going to pass you with a question to display there. That's exactly it. And let's also go in and add in another real quick new item here. And let's add in the correct, which is spelled E-C-T. Okay. By the way, one little thing to get yourself into the habit of, again, you know, speaking of good habits, always have a title. Oh, yeah, yeah. Always, always, always. Okay, so let's just go in. Let's say H2 and congratulations, you're correct. So this is the page that's going to be displayed when somebody has attempted to answer a question and they've answered it correctly. So that's it. Just a nice simple page that says congratulations. You've answered it correctly. And let's go to the other side. Which is if they get it incorrect. Yep. All right, so if this page will be displayed, if somebody attempts to answer a question and answers it incorrectly. So now what we want to do is let's go in. And again, we'll go with an H2. Sorry, you are incorrect. And then let's go in and let's say, div, the answer is, and let's go in. And once again, curly, curly, ah. Cause now, yeah, the nice thing is if somebody's got the incorrect answer, it'd be nice to tell them what the correct answer was. Exactly. So yeah. So we'll go in and we'll call that answer. And then we'll go in and say, div and you said, apparently I've lost my ability to type. Curly, curly and submitted answer. So we'll have to go in and create those variables. Yeah. And we'll go back and do that in a minute. But the big thing that I want to highlight here is I want you to notice that, you know, I didn't do anything fancy here. That I went straight from text into the JINJET and into the HTML. And that's one of the very cool parts is that you could just drop these, wherever it is that you need that dynamic text. So wherever you need it, just boom. And there it is. So just that simple to go in and set up. So I really love, love, love that capability. Cool. But obviously at some point, I could have to go update code to put values, to make sure that when we display that page, we pass some values for answer and submitted answer. Yeah, we'll need to get there. But before I do that. We still have some more pages to go. I think there we are. One more. Creating questions. So this is the page that comes out. Because we're going to let the people who visit our website add their own questions. So this is the page that's going to come up and tell them that we've successfully accepted the question they submitted. That's correct. You asked, and let's just say curly, curly question. Beautiful. Okay. See, just like that. And again, the big thing that I want you to notice here is that 90% of this page is what? It's basic HTML. That's it. And only the little bits that we need here are that bit of Gingian. That's one of the things that I really love about these Gingian templates is that it makes it very easy to go in and do that. Okay. So let's go back to my slide. Just because I think now is kind of a perfect reset point here. And boom, boom, boom, boom. So you've now created all the forms you have listed there. Exactly. So we did the form. We did the basic HTML for correct, for incorrect, and for created question. Okay. Now we just need to update the code to call all of that. Now, I am going to, as I kick back into Visual Studio here, make my life a little easier. There's two little things that I'm gonna need to make this work. Okay. I am gonna need request. Remember, that's what we're getting from the user. Request. So we're gonna use that request.form to ask for values from forms. That's it. And I'm also gonna need my render template. So I'm just gonna call those right now. I need those. Now, one of the things that people frequently ask me is they ask, hey, Christopher, how am I supposed to remember that? And chances are there's probably a couple of people asking that in the forms right now. And my answer is really kind of three-fold. Number one, yep, check out a book, check out the documentation, check out a website, which we'll explain it all. Number two, watch NVA, a video like this. Number three, I guess, take a course. And the number four is to actually get in and do it. Because kind of going back to our language analogy here, what we're trying to do here is we're trying to learn vocabulary. So how did I wind up learning the term phantasmagoria? Well, the way that I wound up learning the term phantasmagoria, which by the way is for very vivid, lifelike, sometimes a little bit weird dreams. So phantasmagoria, the way that I wound up learning that was just through the people that I wound up meeting and sort of a long story. But I wound up learning this word because of a couple of people that I met and through just usage and being exposed to the English language. Sort of that same concept here. So how are you supposed to know this? You get in and you keep reading, you keep learning and you keep using it. And after a little while, it's all going to start to mesh. So a lot of times people will see this and they start to go, oh, I'm never gonna remember this. Here's the great thing. Is there's a lot of blog posts, documentation, classes, videos, et cetera, where you can go learn it and you can refer back to it as well. Don't be afraid to go look things up. We all do it. So don't feel the need to memorize it. Just you will start to just kind of learn this after a little while. Yeah. Okay, phantasmagoria is one of my favorite words. So it was discombobulated. It has such an onomatopoetic quality about it. Moving on. Before I get completely lost, it's too, it's... Okay, anyway. So let's go in and start putting together our create. Now, if you remember, what we wanna be able to do is set up those two little spots here for the get and for the post. That remember with get, this is where we're gonna send down the form that the user is then gonna use. And remember on the post, this is where they've actually given us that data and they're gonna be sending that back up. So that's how we're gonna know do they want the form or are they giving us data. So on the create side, here's what I'm gonna do is I'm gonna say if request method, and for whatever reason I'm getting no completions, but I promise you this will work. And I'm gonna go ahead and say if it happens to be get. So what this tells me is that we need to send the user the form. Right. So this was like when initially, when somebody wanted to comment on the koala picture, we started off by saying, oh, well let me give you a blank form to enter the comment. In this case, we're sending them a blank form so they can enter their question. Exactly. So now I'm just simply gonna say render template and now it's gonna ask me for the name and this is going to be create question HTML, just like that. Otherwise, if it's request method, and if it happens to be post, well now what I know is that they submitted the form so now I need to read the form data and save it. Right. Now, what I'm gonna do is I'm gonna make your life a little easier here. Oh, I appreciate that, thank you. And I'm gonna say title equals request form title. And if you remember from before, we had all that in there. And I'm just gonna make my life a little easier. Answer and question. So these names, when you say request form title, request form answer, request form question, these are the same names that we're gonna see inside at HTML. There we go, title, question and answer. There we go. All right, awesome. So that's how it knows which fields to read from the form. That's exactly it. Now, what I'm gonna do at the very end here is I'm gonna add in an else block just to say return invalid request. You did mention there were some other ways you could submit. I mean, we're only using get and post in our code, but... Exactly, yeah. So there could be other verbs. I don't care about any of them, but one of the things that you should always do is account for the fact that somebody may send up a bad request. So that's why I'm gonna throw in that else block. But in any event, back to our little post here, the next thing that I need to do is store this in the database. So that we can store that and have access to it later on. If somebody wants that question asked. Yep. Yes, this is where Susan will have to do some work. All right, make that note for me. I'll come back later. I promise I'll come back and I'll add some code there. Perfect. And then the next little thing is I want to, it'll come to me in a second. Oh, return the template. So we'll say return render template. And this is gonna be created question. And if you remember on created question over here, we wanted to display the question. Right, so in the template you'd said you're gonna give me a value for question here. So when we call it, we're gonna have to pass it a value for question. And so you'll notice I'm gonna say question equals. Oh, I liked Quesiton. Or Quesiton. Now, you know, this is one of those things here. When you look at that, it sort of looks a little odd. You're setting question equal to question. You might be thinking, well, what in the world are you doing? Yeah, question equals question is a little confusing. Yeah, of course question equals question. You know, generally speaking, yes, that's true. Here's the thing is that the second question is pulling from, I should really draw my line to the right spot. It's pulling from that question variable that I created over here. Okay. This first one right here, this is becoming that brand new parameter. That's the name that was inside created question.html. Exactly. So you look at it and it just sort of seems odd. It's a little confusing at first glance, for sure. And I'm completely with you on that. It doesn't look a little bit odd, but if you didn't just simply go with that, what you'd wind up having to do is come up with essentially an arbitrary naming convention just to separate the parameter question from the question variable. And you do see people that do that. They'll call it like t question equals v question for the variable question versus template question. Yeah, and m and p and yeah, all sorts of things. T question, t question, t question. You know, if it's a question, it's a question and just keep it with that. And honestly, I think in the long run, it is going to make your code more readable. Okay. So now let's go in and let's build up the second one here which is going to be question title. So what we're going to need here is, once again, if our request method is get and this is again going to be where we need to, I'm just going to make sure my tabbing is in the right spot. There we go. Send the user the form. So this is going to be return render template and this is going to be an answer question. That's what I call it. Answer question HTML. And again, we're going to need the question. So we'll say question equals question which means up top here that we're going to need to grab the question. So I'm going to need to say question equals question here. But of course, you know, we don't want to hard code that in. We are going to want to get some data. So once again, we'll go in and say, read question from data store. That looks like more work for me to do later. Yep, Susan, please add code here. All right, then we'll go and say, Elif and request, come here. So once again, this is the idea of somebody's, we're going to, somebody's going to be asking, somebody wants to try and answer one of our trivia questions. So first they pass in a webpage with the category or title of the question they want to be asked. And then we say, oh, do you want that? So we pass them back the question with the blank in a blank form so that they can type in an answer. And then they type in the answer and they hit that submit button and that submit and that form, we said forms do a post when you hit that submit button. Correct. So then when it comes back here, it goes to the post. So they've now typed in an answer and we come back and we can look up that answer. That is correct. Double equals. Now, here's the thing is that we now need to once again, do a little bit of work here because now we need to go get that question or read the answer rather, read the answer from the data store. Yep. To see if they gave us the correct answer. Correct. So Susan, we're going to need some more code here. All right, we'll see what we can do. All right. So what I'm going to do for right now is I'm just simply going to say answer equals answer because I want a placeholder. Sure. And then down below, I'm going to say if it turns out that the submitted answer equals the answer. Right. So we're going to go in and say render template and they were correct. I need to return that, I know. And that one, we didn't specify any particular variables inside that particular render template. So we don't have to pass in any parameters except which HTML template to display. That's correct. HTML and I want submitted answer. Right. Because when we were telling it, we did say design our template for when you tell them it's an incorrect answer that we were going to tell them you answered this but the correct answer was this. Correct. That template. So that one we do have to pass in parameters. I need a colon. There we go. Okay. Now, so we've got all of this now baked in. So just kind of walk through the logic here. What you're going to notice is if it turns out that it's a get, then what we're going to do is we're going to load up the question and we're going to display out the little form that shows the question and the little text box where they can answer it. If it turns out that it's post, what that does is that tells us that they made the submission. So then in that case, what we're going to do is we're going to read the answer that they gave us from the form. We're going to load the answer up from the data store. We're going to check to see if they got it right. If they did, we send them correct. Otherwise, we send them incorrect. Okay. That's sort of the review there. Now, the last thing that we need to do is we need to also add in the methods that this is now going to accept. We need to tell it to actually accept both get and post. Now, in theory, this also kind of means that I don't necessarily need that invalid. I still like to have it there just because I think it's a good practice that if you know that there's potentially multiple items here, that it could be that it could be, you know, get, post, delete, and a few others, let's just make sure that we've got a catch all. So that's why I like that down at the very bottom. Okay. Now, give me two seconds. I'm just going to scan my code. Give it a glance through. And I just want to make sure that I can actually call something here. So let me, we're really cooking here. I give this a 70% chance. All right. So create a question. Let's hit create, title. Hey, can you do me one quick little thing? Could you bring up that command window again? Cause I think it's neat the way you can see if it's doing the get or the post. So we can see how the first time is actually bringing up that page when it's a question form. You can see it's doing gets, gets, and gets. It hasn't actually done a post yet. Correct. Yep. And by the way, ignore the fave icon that just, yeah. Okay. So there's that. So let's go in and I'm just going to go very creative here. Test question is, when was the battle of Hastings? And I'm going to go with 1066, which is the right answer. And I'm going to click submit. And sure enough, you're going to notice that it tells me, thank you for your question. You asked, when was the battle of Hastings? Now you'll also notice that I did in fact set all of that up. But of course, I don't have a data store. So it's not actually stored behind the scenes. But the main point that I want to highlight here is the fact that this is baked off of that template. And to go all the way back to something that we mentioned earlier this morning, this is going to work regardless of the browser. And you'll notice there's no way that I as the user can tell that this used a template. This is HTML. I have no idea that this actually used a template. And if I bring up a non-competitive browser from another company and I paste in that exact same URL, chaga, chaga, chaga, come on. Did I close out my command prompt? Oh, okay. There it is. Just taking some time. So we'll go with test and what is your name? And Christopher, that really trivia question, and hit submit, you're going to notice it works. So again, regardless of the browser, it still works. Right, because, and you can't even tell it was written in Python. Exactly. And that's the whole thing. Yeah. It's just HTML that gets sent up to that browser. And what the server is doing is irrelevant. Cool. So just to kind of review here, we've now got the create and question methods created. Yep. We've got our create question and our created question. Yep. So both steps there. And then answer question and both the right and wrong there. But the last thing that we're missing is the data store. Right. That's your job, but I'm hungry. I think everybody could use a little break because it's amazing how much you guys, if you look at that code now and how much you've really mastered, there's a lot of content. Yeah. So really, you know, what did we learn here? Well, you're going to notice that we learned how to create and use those JINDA templates. Yep. We learned how to create those forms. And so now we actually have enough to start creating real world applications that don't use databases. Yeah. We'll get to that. Yeah. But let's go ahead, we'll take a meal break and we're going to be back in about an hour. Enjoy. See you soon. All right. Well, welcome back to Introduction to Websites using Python and Flask. Alongside Susan and Ibeck, I am Christopher Harrison. Now, up until this point, we've been building out our server-side components on Flask. We took a look at our JINDA templates and we really got a very nice structure around an application to start doing all of our little trivia and storing and asking questions and so forth. But you know what we need? Well, we have a basic problem. Somebody answers a question and we have no way of remembering what question they gave us. Yeah, we need somewhere to store all of that. Yeah, so what can we store this data? We're going to need some sort of data store. OK. So that's what we want to focus in on now. So up until now, we've been very focused on how do we communicate between the browser or users at the browser doing something, sending information back to our Python code, sending information back to the user. But there are times we need to remember what happened in between or from session to session. You think about it. If you're placing an order at an online store, well, we need to be able to remember what you ordered so we can ship it to you later. So we do need a debate to store that information. So what we're going to do now is we're going to talk about some different data storage options. And then we'll delve into one of them in the ticketers so that you have at least a couple of different tools in your toolkit that you can use to remember values. Perfect. I love it. All right, so let's jump in. So lots of websites need that ability to remember data. If you think about it, order information on online stores. You can ship it when it arrives. High score tables on video games. Just remembering your favorite products, what you looked at last time you were here. That kind of stuff happens all the time on websites. Yeah, I basically say that websites really are just a front end to a database. When you get right down to it, that's quite frequently it is, hey, here's my facade, my database in the back, and we're just going to be sending data back and forth between there. Yeah, exactly. Now, there's a lot of different ways you have so many choices, really, in terms of how you actually physically store the data that you need to remember when you're on a website. One of the options is to store data just in a text file. Yep. You know, you've got code. You can write code things, store it in a text file, and read it back when you need it. XML files. And I'll explain what XML files are in just a moment. We're going to get to that. Relational databases. That's definitely another popular option as well. I said, and I will explain what makes it a relational database in particular. And the idea of what we call no-SQL databases. That's another term you hear a lot. So let's basically take a look at each of these options, maybe a little bit of the pros and cons of these different choices. I like it. Something tells me that no-SQL is going to have no-SQL. You think there's no-SQL used for no-SQL? I'm going on a limb here. But I'm going to go on a limb and guess that somewhere else there is SQL. OK. Yeah, so that's the corollary to that. OK. So when you get down to trying to make that decision of which data storage option you should use, the answer is always going to be the dreaded, it depends. That is the generic. If anyone ever asks you, how should I do the following in insert programming language here, the answer is, well, it depends. Always. It depends. It's the safest answer for everything. But in this case, it really is true. So let's take a look at those four basic options and just talk a little bit about what they are so that maybe you'll be able to make the right decision and figure out when it depends on what. At least you know what it depends on. So the first option is to use a text file. And if you text files, usually just comma separated variable files, you can open them up in things like Notepad. And they're just files that you can store right on the file system, same place that you're storing your code. And they can contain text data. As said, most of the time we'll use these comma separated variable or CSV files. And so there's a typical sort of file there. And they work very well. If you want to store very simple data, it's a perfectly valid way to store information. Yeah. If you just need a couple of nodes, a couple of just very simplistic key value pairs, just someplace to just throw some data, the text file will work. It will, absolutely. Yeah, not the most robust solution. No, no, it will work. It will work. And if you took the introduction to Python MVA, we actually covered in modules 11 and 12, we covered all the code you can do in Python to read and write from text files. So we have covered that. I'm not going to go through it again. But that is absolutely an option. So what we showed you in that course is a real world scenario that is sometimes used. The limitations, though, of text files, if we actually take a look at this sort of file right here, one of the things that you run into is if you take a look at it, all the records, we've got a bunch of records at the top. And these, I know, these represent different people and their ages. But underneath, I have some information about some companies. And the problem is, if I write a program that's going to try and read this information, one of the problems it's going to have is it doesn't know when am I looking at an employee record and when am I looking at a company record. So it's going to read Northwind Toys Company and think that's a person's name. And when it sees 11 any street, it might try to read that in as an employee idea or as an age. And then it's going to go, what's this Toronto, Ontario, Canada stuff doing at the top? And it's all messed up. And on top of that, what you'd be trying to do is convert the age into a number. You're going to see 11 any street. And then all of a sudden, things are just going to blow up at that point because it's not going to be able to convert 11 any street into a number. Right. And this is what we say text files are not a particular robust way of storing data because we have no way of saying what data type is this. What is this data? The programmer has to know how that data is formatted. And the person who creates the file had better create it right because if they don't create it right, it's going to blow up when you try and read the data. Absolutely. So yes, it works. But not always going to be our best solution. Yeah. I've spent a lot of time on any street, by the way. Have you spent a lot of time on any street? Yeah. A lot of time on any street. So the other option, of course, if you're worried about, OK, I can't tell if it's an employee information or a company information, a lot of people might choose to split it across two files instead. So if we look at this example here, again, we've got information on companies and we've got information on employees. And you go, well, hey, I can solve that problem not being able to tell them apart. I'll just put them in separate files. I could see a lot of files being generated by the end of that. Yeah. You could end up with a lot of files. And this will, again, this will work. And another one of the things about this, and you will see that very naturally, there exists when you start working with files and with data. But there's often a relationship between the data and the different files. There's a very good chance here that certain employees may work at Northwind Toys specifically. And some of these employees work for tailspin toys. So they're working at different places. How do I know that by just looking at these two files? There's nothing to indicate which employees work at which company. I don't have a way of doing that. No, you really don't. You really don't. I mean, you're basically just sort of on your own to try to figure out, OK, well, now which is which. And if you tried to then start inserting in some brand new rows, things could go sideways in a hurry there. Yeah. And that sort of type, that type of data comes up a lot in different scenarios. If you think of customers who are placing orders at a company, if even in a trivia application like ours, we can sort of set up, you might be able to request different categories of questions. And then you get all the questions for that category. Just being able to do that, like, what is the list of categories? What are the list of questions per category can become very difficult if you're just using text files. But again, if all you want to do is store a few values so you can look them up later, absolutely, you can do it with a text file. It will work. So a couple of other limitations to be aware of when we talk about pros and cons. One of the other challenges is, if you only want one record in the file and the file has 500 records in it, guess how you find record 143? You read one, record one, record two, record three, record four, record five, record six, record... Okay, I've done now. Until you... You're just doing this the whole time, just looking at the index cards. Yeah, exactly. Nope, nope. Just imagine, you know, if the rule was, if you were trying to look up, remember there was a time in our lives we had these things called phone books. A what? A phone book, and you could look up phone numbers in them. But imagine if, if you wanted to get one number out of the phone book, you had to read all the numbers before it. That's gonna be a very slow way of looking up somebody's phone number. So, again, it's not gonna be the fastest way to retrieve a single record. If you're always retrieving all the values, it's fine, but if you're constantly just trying to get one value back, that's again a place where text files start to fall apart in terms of not being the optimal solution. Right. Sorry, we covered that. Somebody's going backwards instead of forwards. All right, now let's take a look at another option. This one's sort of, it's interesting. It's sort of a transition to the world of databases, but so it solves some of the problems of text files. Okay. And that is an XML file. An XML, if we take a look at an XML file, if you take a look at this file, it may kind of look like some other code we were looking like this morning. Because... It looks kind of similar. Yeah, it may look a little bit like, look, we have open and closing brackets, angle brackets, we have the idea of opening and closing tags. This looks a lot like HTML when you open it up. It does, it really does. In fact, HTML stands for hypertext markup language and XML actually stands for extended markup language. So it's intended to look like HTML. So that is quite deliberate. But what's interesting about XML is in the end, it is just a way of saying, here is some data. Whereas HTML is designed for you to tell a browser, hey, I want to put a text box here and I want this text to be in bold and I want to put a button here and create this form. The XML language is designed to say, I have a record and this is a list of employees and each employee has an ID and a name and is a company that they work for. So that's how XML is designed. It's tags are all designed to let you specify, here's the information that I'm storing. So you're describing the data then rather than what you frequently do in HTML and you should try and stay away from it but you can often describe in HTML how you want the data to look but not necessarily describing the data. XML is all about describing the data. Yes, it describes the data. So if you take another look at this example XML again, now what's neat about this, you think back to our, when we had just a CSV file, whoops, that's what I went to do. So if I had a CSV file, this would have just been but I had Doyle McCarthy here and then I had two Jody Mills. Can't type apparently. Apparently I should be drinking caffeine. So if I had done it that way, you can see sort of I get this, this would be what it would look like in a CSV file. But how do I know that the value of one is an employee ID? I don't. It's only based on position and what would happen if somebody else who wrote into that file flipped those two? Yeah. You'd be in real trouble at that point trying to parse and figure all of that out. Whereas, right, so if somebody put in Doyle comma one instead of one comma Doyle, suddenly I'm trying to read the file it's gonna mess things up. The neat thing if we look at the XML is you'll actually see that I say, here's the value one, but I specifically specify that's an employee ID. And this is also for the employee, this employee also has a name. And that employee's name is Doyle McCarty. So for each employee, I have that ability to be very specific and to describe as you put it. It's describing the actual day of saying, this is employee information. What am I telling you about the employee? I'm telling you their ID is two. And that their name is Jody Mills. And you can tell that without knowing anything else in advance. And really, even if you didn't know anything about XML, you look at that document and it basically just describes, hey, this is what we got going on here. Yeah, exactly. It's fairly intuitive. Building them for the first time is always a little confusing, but it's funny, if I'd handed you that file and said, what do you think this is? You probably would have figured out it's a list of employees and that's their IDs and names. So it's also very self describing. And that's another nice thing about XML. So those tags said, describe the data inside the file. So we can see those different names and IDs. The other interesting thing about XML is we can mix and match different types of records in a single file. So it's perfectly valid. In this case, I have a list of employees, but they're all belong to the company. So I specified, first of all, wait, first I have a company and that company is Talesman Toys. And here's all the employees that are part of that company. So those elements act as containers then? Yeah, I'm sort of showing a parent-child type relationship also. So the parent company here, for his parent company of Talesman Toys has this list of employees. For this company, here's the list of employees. And along the way, I can provide you information about each company and information about each employee. And anybody reading the file can tell which employees go with which company. I can tell if it's company information or employee information based on where it's located inside the file and how it's described. And you can even kind of keep going with that hierarchical structure where you go in and say maybe here's the employee and here's the people that they manage and the people that they manage and kind of break all of that down. And then through code, you can kind of explore all of that and bounce your way through the XML file. Yeah, absolutely. It's not limited to one parent-child. You can have grandparent, parent-child, grandchild. Yeah, you could show a company has, this company has these departments. Those departments have these employees. Those employees have worked these shifts and go as far down as you want. Yep. So that's the idea of XML files. Now it is the other thing we mentioned there was a problem with text files is if you wanted to retrieve one record, you had to read the whole file. One of the neat things about XML is it has a query language. So there are specific languages and commands you can use to query XML files. Yep. There's XPath and XQuery. So XPath basically allows you to specify a path that points to the record you want, whereas XQuery literally allows you to say go look in the file and find a record that matches this set of criteria. Yeah, XQuery is much more robust than XPath. You can actually do kind of a couple of really cool things with XPath and going in fine attributes and so forth. But if you really are trying to get that full power and do things like for loops. Or say get me all the companies in Tailspin Toys. Yeah, exactly, yeah. Just those companies. XQuery is gonna give you the ability to do that. XPath will point you to it and then it's still up to you to go in and read the rest of those values. XQuery will really let you get into all of that. And you'll notice that most of the surrounding technologies with XML start with the letter X. They just, you know, yay. XML, XQuery, XPath. Yay, letter X. It's really good when you're playing the alphabet game, because I can never come up with enough to start with X. Absolutely. And today it's brought to you by the letter X. That's right, or at least this module. Yes. So we have these languages and these that we can use to query and get individual records back. So that's, again, another improvement over basic text files. Now, in terms of drawbacks, XML files can get very big. Yeah. They're picky. If you forget to put the closing slash employee on there, then when you try and query the XML file, it goes, I can't read your XML file, because somewhere you forgot to close a tag. They're also case sensitive. Yeah, they're case, HTML isn't case sensitive. XML is. So those types of things, so they're very finicky about the syntax. Said, don't, if you forget a closing element, then it just comes back and says, I can't read your XML. Yeah, it is case sensitive. The files can get quite big. Those are the drawbacks. But is that certainly much more powerful and can be more efficient than straight text files? Absolutely. It's on libraries out there, but actually support working with XML files. So if you want to explore this, two of the more popular libraries that contain functions that allow you to do things like sex query and to read XML files, beautiful soup. I love the names they come up with for libraries in Python. Beautiful soup, of course. No soup for you. And LXML, bad, hey, come on, you're not the only one who can make bad 80s television references, come on. So an LXML are two popular libraries, which will help you out. So if you wanna try XML files, we're not gonna cover it here, there's too many data store options for us to cover everything, plus XML. There's actually a lot to it, and we could, is there an MVA out on XML yet? Yes, no, we'll find out. Processing. But literally, you could do a full day course on XML without any difficulty. Something tells me we probably have. Yeah, we'll find out if there's an XML course. We've got a challenge for Christopher there as I keep going. Developing Microsoft Azure Solutions on the 19th with Brett Statham and Sydney Andrews, that should be fun. It doesn't look like we do. Okay, so we may have a new MVA idea to come up with. But there's a lot to XML. So again, it's one of those ones, if you want to delve into that as your option of storage, you'll wanna take some time to learn that and spend a bit of time learning your way around. The next option, and this one's extremely popular and used in a lot of any of the really big sort of enterprise solution websites and that's to use a relational database. So this is what you're gonna see if you're going to store and you're ordering things online, there's probably a relational database on the backend. If you're using a company expense reporting system that where you enter your expenses, that's probably all being stored in some sort of relational database on the backend. So relational databases, they're made up of one or more tables that contain data. So if we take a look here, I've sort of got two tables. The first table here, this is sort of my customer table, if you will. And for each customer, I've got an ID, I've got a name, I've got a city for where that person lives and I know the country where that person lives. And then I also have a orders table, which is keeping track of the orders each customer placed. And there is a relationship here between the two. You can see here that Sacha being inspired has decided to purchase himself a book on coding with Python. Wow, we have that kind of influence. I know, I know, you just wait to see what Sacha's talking about in his next webcast. And Susan on the other hand was so inspired by all of this cool stuff that Christopher's talking about that I had an urge to run out and pick up a book because you can see that I have an ID of 106 and customer ID 106 purchase the book on building websites. Okay. So I have one or more tables but there's relationships between the tables, right? I know which customers are going with which orders and that's what makes it a relational data. So there's always gonna be, or there's frequently going to be two tables and there'll be one column that exists in both tables. They don't have to have the same column name. You know, in the customers table, the ID column is referenced by a customer ID column in another table. So again, looking at the slide, you can see that we have an ID in the customer table that allows us to tell which orders were placed by which customers. Absolutely. So those values, that's why it's a relational database. That's actually where the word comes from. Exactly. One little thing only just because it's me and I've got to say it. Typically when you see those column names, they won't have the spaces. We did that for readability, but yeah, you might not see the spaces there. Yes. It's one of those levels. I understand, yes. Even though some databases will support spaces and column names, I'm completely with you on this because as a person who spent many years working with databases and as a coder, I really don't like working with column names that have spaces. So be nice to fellow developers. Don't put column names or spaces into your column names. And don't do underscores either while we're at it. Yeah. Yeah, I don't know about you, but at least for me that, you know, hitting that underscore when I'm trying to touch type, it usually takes me about like five shots before I can find that underscore. See, we can't stop ourselves. Relational databases is another big topic. You know, there's like a whole MVA on that. Somebody posted that we should have a T-shirt that says, there's an MVA for that. Absolutely, that'd be an awesome T-shirt. I can see that coming, coming soon to store near you, or at least a laptop sticker. I like that. There's an MVA for that. Mr. Calder, paging Mr. Calder. When we wanted to read values from a text file, we would have to read through the entire file. When we wanted to read a value from an XML file, you could just read the entire file line by line till you find what you're looking for, or we mentioned you could use libraries in XQuery to request, say something like, give me all the employees in company Northwind. In relational databases, we use a language called SQL. Ah-ha. So this is why there's- So there's the SQL, so no- This is where- Okay, gotcha. This is a yes SQL database. Yes SQL database. This is a yes SQL database, instead of a no SQL database. Because SQL, or structured query language, also sometimes just called SQL. This is the language we use to ask the database for information to insert and manipulate the data inside the database. So you can say, give me all the customers with all the orders for a particular customer. I can say, go add a new order. I can say, delete an existing order. So again, you just take a quick glance at the slide. You can see a basic example of a SQL statement. Select star, just mean select all the information for Bill Gates from the customer's table. So not gonna teach you SQL here. I know there's an MBA on SQL out there, but that's how we communicate with a relational database. What's great about relational databases, you can store very, very large amounts of data very efficiently. That's what they're good at. They're good for storing large amounts of data and letting us query it in a very efficient manner. You can also keep track of the relationships between all of the different records. Who ordered what? Who works for who? Which account belongs to which customer? That's what relational databases are really good at. You can also search for exactly the records you want. The database tool is actually going to be able to find the record you want and give you back just the record you asked for. So that cuts down on the amount of data that's being sent back and forth and it makes queries faster and less traffic on your network. Yep. And these days, hey, with all our mobile phones, we're all starting to care about that a little bit more. A little bit. So you get back only the data you need. Now, that all sounds awesome. You're like, wow, it does everything I want it to do. So why don't we always all use relational databases? Well, if they do all that, they have a little overhead involved. If you're going to use a relational database, it's actually separate software. You can't just go into Python and say, create relational database and start querying it. It's going to be separate software, but you have to install somewhere on a server in a place where your Python code can connect to it and access it. So examples of relational databases include SQL Azure, SQL Server, Microsoft Access, MySQL, Oracle, those are all examples of relational databases. But that's a separate product. You have to go install SQL Server, and then you have to create a database on SQL Server, and then you have to create your tables, and then you have to load it with data. And then you go to your Python code and you say, connect to that database I made over there. Go look in the table I made over there and start inserting data into it. So there's a lot more upfront work involved. It's great when it's all up and running, but if all you want to do is store the high score for a game. My gosh, that's just major overkill. I want to create all that just so I can store a high score. There's one, let's keep it simple. So basically the main point that we're trying to make throughout all of this is there's that old saying, if the only tool that you have is a hammer, everything looks like a nail. And of course, that's not the case, that a hammer's good for a particular task. But you also need screwdrivers and pliers and everything else. And that's really what we're trying to do here, is just going to show you, hey look, these are all the different tools that are available for you, and they each have their different advantages, disadvantages. They all have their different places and their different purpose. Yeah, then we're just trying to help you understand which one's right for the different scenarios you're going to encounter as you start building more applications. Yep. The next option would be to use a NoSQL database. It's funny, now I always call it NoSQL, never NoSQL. It doesn't sound right that way. NoSQL just rolls off a tongue better. There you go. So a NoSQL database is basically, it's a database that stores data. So obviously these are all used for storing data, but it doesn't store them in tables with relationships the same way for relational database. Right. There's a number of different ones out there. If you've ever heard of people talking about Mongo, again, I love the names of things, Mongo and Gingya and all these wonderful things. You really can completely confuse your friends. Post something on Facebook about the fact that you're learning the difference between Mongo and NoSQL versus using XQuery on XML. And I promise you, your friends will just look at you completely stunned. But if they understand you, all right, you found a fellow geek. But so you can create their database like Mongo is very good at storing documents if you want to store a lot of documents. Or if you need to do a lot of graph stuff, there's OrientDB which designed for that. And or maybe just key value pairs. So I just want to remember a few values and I can want to name for each value so I can remember which value goes with the thing. So I want to know first place score, second place score, third place score. Then I can do that with what we call key value pairs. And Redis is an example of a key value pair database. And MongoDB actually you can absolutely use for key value pairs as well. It's another popular one for that. Now this is my pet peeve though. Is I meet a lot of startup companies and initially they're starting out. They don't want to spend the money or the time to build that infrastructure of full relational database. So they start off with a Mongo or Redis. Awesome, that is great. And then as their website gets more complex and they're trying to do more and more things they start trying to basically do weird things with their Mongo database to basically try to get it to do all the things that relational databases do automatically. So absolutely, Mongo and Redis are great but when you do as it gets bigger and you find yourself going wow, it isn't doing what I want to do. I'm going to have to come up with some creative way to rework around that. Stop yourself and go wait a second. Is this getting big enough and convoluted enough maybe it's worth the infrastructure of a relational database. Because I've seen so many companies said they start off with no SQL and then they're so caught up in that that they start writing thousands of lines of code to try and do things that are all done for you if you just use SQL. Right, and kind of going back to something that we talked about earlier with design that one of the main points that we made was that separation of concerns or views display out the data. One of the big things that you could do is when you set up the methods inside of your routes file or files if you've got multiple. One of the things that you could do is really again just call out to a separate class or to a separate pie file that has the functions that do all of that behind the scenes. Because when I get into my routes pie file and I go in and I say create if I've got a little method that's going to store that inside of a database and I've got another method that's going to pull that back in from the database I don't care where that database is just so long as I know that it's going to store it and when I ask for it back that it's going to give it back to me. So what's happening behind the scenes really just becomes a black box to me. And if you design properly what you can do is make that black box pluggable. So that way maybe you do start out with Redis or with MongoDB and then you start to grow and you start to get a bit more complex and you start to realize, hey, wait a minute. You know, we really do need to migrate over to let's say SQL. Well, you can do that with limited impact on the rest of your application that you go update the data access portion but you leave everything else the same. And again, my code all I'm doing is I'm just simply saying store question, retrieve question or whatever your calls might be. And as long as again, it's going to store the question and retrieve the question in that little black box. I don't care what that black box is. I don't care where it's doing it as long as I'm getting the behavior that I expect. So you can make those types of changes from database to database and limit the amount of impact that that's going to have on your application. Yeah, that's where good designing your code. Yeah, you may have somebody on your team who's really good at figuring out how to talk to databases or when you're really good at that or you're really focused on that code. Yeah, make a module of it's making the connection, asking for the data and that passing it back in a function. And then yes, in your other module, you say, hey, get me that value, would you? And yes, it'll make your life easier when if you come to a point where you need to change data stores and you'd be surprised how often that could be useful. Now, so Redis, if I take a look here is an example of a key value paired database where said great if you just wanna store a series of values. So you can have something very simple. So I have a value, I wanna keep track of a number of people who visit my website. And so what I do is I have a key and for that key, I store a value. So basically I just have number of visitors. It's like a variable, really. And key is like my variable name and the value, the value I'm storing the variable. The only difference is I'm storing it in Redis and we call it a key value pair instead of a variable and a value. But aside from that, it's really the same. You can have some more complex names as well inside there. If you're example, I can actually start creating sort of structures of my variable names if I want to. So here, whoops, wrong one. I have actually created a variable name or a key which is user colon first name. This is actually quite common in Redis. A lot of people use this convention. It's a way of just sort of saying I want to keep track of all my user information. So I might create a key called user colon first name and a key called user colon last name. So I remember both of those keys are information about a user. So you can create sort of a structure to your key names to help you keep them straight. One of the most popular key value databases out there is Redis. And that's actually the one we're gonna use as the back end for our database that we've been working on. So, but remember the data store is not part of Python. One of the great things Christopher talked about this morning was that one of the reasons we liked Flask and we liked Python was you can get started with it really quickly because it's very minimal but that later when you needed to do extra things, you would need to add more components and install more pieces. So if we want to use Redis, we're going to have to install it. To install it, there's a few things we'll need to do. One, you literally need to build the Redis database or Redis product on your machine. So- The Redis server. Yeah, the Redis server. You're gonna need to go to easiest place to find it is off GitHub. There's the link for the Windows setup file. There's different ones for different types of operating systems. This is not a Windows specific product. And then once you've got that installed on your computer, you're going to need to install the Redis library in your Python project so that your Python code can use the methods that are used to talk to Redis. And we're gonna need to add that package to our virtual environment. Somebody actually asked this in the Q&A during lunch, was, hey, you know, so I downloaded a module five or whatever it was and it's saying, hey, I don't have Redis, how do I get Redis? Aha, well, let us answer that question. Yeah. And the last thing you're gonna need to do is you're gonna actually have to make sure that Redis, the Redis service is actually running on the computer as well because installing software doesn't mean the software is running. So we're gonna have to go to task manager and make sure Redis is running. So what we're gonna do now is I'm gonna flip over to Visual Studio and what I need to do is I'm gonna need to go over to my environment here. Now, you've already got Redis installed. I did. Yeah, you've got Redis installed and up and running. Yeah, so I'm gonna show, but I still will still show how you check if the service is running. But yeah, I have already done the step of installing Redis because I didn't wanna sit here and have to do a little, oh, wait, wait, was it a different dance for installation while you're waiting for things? Yeah, it's more. This was a slide dance. This was a slide dance. Well, yeah, we're not gonna do this. Okay. But it was sort of like, and now I'm trying to remember. It was sort of this sort of thing. Yeah, more of like the head moving. Because you're moving the mouse along with it, so your head just kind of wants to bob along with it. I can't keep up with Christopher's dancing skills, so rather than having to do an installation dance while you watched it install, I pre-installed it. By the way, excuse me, Mr. Berry. Yeah, this is not to wind up on outtakes. That's all I'm saying. Okay. All right, there we go. Yeah, it's a good thing we're not live. Good thing we're not live, absolutely. Yeah. So what I will need to do is I still need, so I've got Redis software installed, but I need to make sure that the service is running and I need to add Redis to my Python environment. So let's start by installing it into that Python environment. So I'm gonna go to my program and I'm taking the same project that Christopher finished up with at the end of the last chapter. Yep. I'm going to my environments, right click and saying install a Python package. So we'll do that, install Python package, and literally you just type in Redis because that is the name of the package. When you select that and you select okay, it will go ahead and you'll be able to see in the bottom little left corner in the output window, Redis was in fact, installed successfully and I can confirm that by taking a look over here in my Python environment and you can see Redis added to my Python environment as well. Okay, so I have the Redis package. I need to make sure that the service is running. I do that by bringing up task manager and inside task manager, I'm gonna go to my services and I'm just gonna check in order. I'm gonna do this alphabetical order here, scroll down to the R's and sure enough, there is my Redis service and it is currently running. If it wasn't running, I would just right click and say start. If you're at a big company, you might occasionally run into problems where you don't have permissions to do that. You might need administrative privileges to do it but if you're working on your laptop that shouldn't be a problem. So I have it installed, I have it added to my environment and I have the service up and running. So how do I actually write code to connect to it? Well, once I'm gonna need to import the Redis library so that I can access the coding environment just like we had to import Flask and import the use for an import render template, we're gonna need to import Redis. Then we have to create a connection to that Redis data store using a function called strictRedis and the syntax is pretty straightforward. It looks a little confusing but the nice thing is it's very little you ever have to change here. So this follows into the category of the cut and paste this line of code and it's probably just going to work. So it's, I'm creating a connection, I'm calling my connection R in Christopher's speak. Yes, it's great for talk, like a pirate day but that's not till September though, gentlemen. Redis? Just get all the fun out of my day. Every day is like a pirate day. Every day can be talked like a pirate day when you call your connection Redis to R. Absolutely, and every day is like Sunday. Yeah. So we go Redis dot strictRedis so strictRedis is the function we're calling to create our connection and we have to specify where is this Redis service running? Well, I've got it running on my PC so it's on localhost. So the value I type in there has to be the name of the machine where it's running. I said I have it installed locally so that's just called localhost. It'll be the same for you. The port number is gonna be 63.79 and the database number is going to be zero because I haven't created specific database, new databases in Redis. So really you can literally cut and paste that line of code that's how you're gonna connect to your Redis database as well. The only thing that might change is if I was trying to run Redis and it was installed on Christopher's machine I would have to find out how to type in the address of his machine instead of localhost. So if we try it, cause that's really a test. And I go in here, let's see and first I have to import Redis. So once again, I'm gonna need to import it. And what I'm gonna do is let's start off initially. I'm actually just going to, when we go to the main page I'm just gonna connect to Redis right there. Perfect. All right, so I'm gonna create my connection R. R. I'm sorry, I can roll my R's. My mother from Scotland so I can roll my R's very well. And call it Redis, dot strict Redis. And the IntelliSense does pick up that function name. And it's awesome, I love the IntelliSense here as well for helping me remember what the values are I have to enter. Hooray, IntelliSense. Yes, love IntelliSense. And the host is going to be localhost. And while she's typing this in it's worth mentioning that those values, the localhost, the ID, the port and then the database are the default. So you could actually just say strict Redis and in theory it would work. But it's always a best practice to type those types of things out. Because you never know if maybe the defaults will change a little bit later. So yeah, so you've got it just like that. And then the other thing that I wanted to mention is that those first three parameters are positional. So you could have just gone localhost port and DB. But you know again, it's nice to type it out as well. So that way if somebody else comes along, maybe they haven't done Redis before. They can look at that and they go, oh okay, well there's the host, there's the port, there's the database. Yeah, absolutely. So this line of code, I'm gonna show you three different lines of code. They're all equivalent. I could have actually done this and just said call strict Redis. Yep. Whoops. We all know Python cares about the positions here. Or I could write this line of code this way. As you were saying, because localhost parameter it expects, port is a second parameter expected and DB is the third parameter expected. I don't actually have to tell it. Those are the values for database, port and host. These three lines of code are all equivalent. So I'm just gonna comment that out here. And I'll just make a little note here. Alternate ways to connect to Redis. Sort of like the movie Clue with three different endings. Each command is equivalent really. Totally personal preference. What I have, the reason I like to list it is it could help me remember. The equivalent. Eventually I will spell the word. Is it helps me remember what those parameters are and that way when I haven't looked at Redis for several, all that time, it's easier to come in. Christopher's losing it over there. Every time now we say R, it's just, yeah. Okay, we're gonna talk like a pirate day now for the rest of the day. Ray! R. I'll get it, we'll get eye patches for the next module. All right, now how do I know if it's worked? Well, actually to be honest, I mean you could start writing try catch statements here. You could. And saying if it does. But really, to be honest, this is the simplest way to test it. Run it, if your webpage comes up, you connect it. Yes. If your webpage does not come up, then you probably didn't connect. That seems pretty simple to me. It's pretty straightforward. So if I just go ahead and run our application, of course, needing to rebuild it along the way. And there it's off and running, it's trying to connect. And look, I can go in. I can start creating questions. I have successfully created a connection to Redis. Well done. So at this point, I think what we'll do is... What did we learn, Susan? I was gonna say, let's just sort of take a look at that here. What did we learn? So we've made it running. We've learned about sort of some data storage options and some of the pros and cons between them and how to install Redis and connect to it. So I'm gonna now quiz you to see what you did learn. So aside from the fact that it's now become talk like a pirate day. If you had some scenarios, I'm gonna throw some scenarios at you and I want you to think about which of the data storage options we discussed you think would be the best option. Because that is one of the things we've tried to do. If you're building an online store that sells DVDs and books and you want the user to be able to see the list of books by author, subject, price or publication date, which of our data storage options do you think would work? You know, I'm seeing a lot. And you know, one of the things to highlight if I can just, you know, tangent. Tangent? Tangent mode. There we go. There we go. So over here on tangent mode, one of the things that's sort of worth mentioning like Susan had highlighted earlier is that we could use really any of these databases for all of these possible solutions. So now bringing it back to the original question, because of the fact that you've got all of those different types of data and so forth, I would say you would want SQL Server. Yes, yeah. I think that's good. In this case, a relational database. Such as SQL Server. All right, I like that. Okay, you're building, say a quiz website. Okay. Like that would ever happen, I don't know. And you need to store the questions and the correct answers to the questions. You know, in this case, because of the fact that we're going with just the very simple questions and answers, I think Redis would really be the best option there. So in no SQL database. Yeah, no SQL, that key value pair. Yeah, you could use a relational database if it was a really complex, if it was something using to store exams and exam questions for university, you could do that if you wanted to. Exactly. Yeah. You want to keep track of a number of visitors who came to your website. It's the kind of thing people often do, you know? They just want to store a number of visitors. You know, if that's it, just a number of visitors, toss in a text file and be done with it. Yeah, if that's all you need. That's it, yeah. Single violin, toss it in the text file. Yeah, absolutely. If you're already using Redis for something else already, then you could store it in Redis. Exactly, yeah. Yeah, and that's it, is that, you know, if you were doing a lot of different things, it's not like you have to say, well, one type of data is going to go over here, one type of data is going to go over here, one type of data is going to go over here. You can decide this is the data store we're going to use and put everything there. Or again, you could, in certain cases, move different types of data into different spots. So if you just needed, you know, like caching key value pairs, Redis cache, hey, there you go. You know, Redis would be perfect if you're looking for just a single symbol value. You know, you could toss that into a text file. So, you know, you really don't have to decide on one solution and just be locked into that. You can go with a lot of different solutions. Yeah, absolutely, so yeah, so awesome. So what did we learn? Basically, we learned some of the pros and cons of our different data storage options, like text files versus XML files versus relational databases like SQL server or no SQL databases like Mongo or Redis. And we also learned how do you actually install Redis and connect to Redis using that strict Redis function. So what can we do with this? You can now install Redis, which you're going to need to do if you want to keep following along with us because we're going to next module, we're going to learn how we can actually store our questions and answers using those Redis commands. And we learned how to create a connection to our Redis database from our Python code. Absolutely, yeah, so we kind of got nice and rolling. Now I am going to real quick here, one last time I am going to go into tangent mode only because I just want to highlight real quickly that once again, this is the first time that we've been doing live close captioning on our MVA on our live jumpstart. And as a result, we're trying to kind of gauge feedback and things like that. So if it's not there right now, sometime in about the next 30 seconds, he said pausing long enough, there's going to be a poll down at the very bottom asking about the close captioning. So if you found that it's been helpful and so forth, please, please, please let us know. And be honest, if there have been issues, let us know that as well because that's the way that we're going to get better. Okay, cool. So with that, what do you say we take a break and then let's come back and actually put some questions into that Redis data. Yeah, let's start storing some data into Redis. Exactly. I like that. Awesome. Perfect. All right. We'll see you soon. All right. Welcome back. Welcome back along. It's like pirate geek girl. It's like I'm going to keep going with that our Redis connection. Arr. So what did we leave off with our pirates? No, we left off looking to stored data inside of our data store. And so let's go ahead and now roll into how we're going to do that and close out the building of our little trivia application. Yeah, exactly. So we're going to need to go back into our code and actually add the code to actually start saving values to the database. I'm very interested to watch you type one. With what are you? One iPad works well. Two iPads is not so well. You know, one iPad's looking pretty cool. Two iPads is, yeah, one too far. Not looking. Yeah, exactly. So after we've installed Redis, which is what we did in the last module, now we need to figure out how we're actually going to use it. So, and forgive me, I'm going to lose the iPad because otherwise I can spend the rest of the day with a red band across my forehead. It's actually still a little bit of a situation. I'm sure I'm going to have a little line for the rest of the module. I can live with that. So we've already talked about sort of how to get started with Redis, how to connect to the actual Redis data store itself. That we have already covered. And that we did with the strict Redis method. And by specifying, most important there was specifying the server name and we specified the local host because we have installed the Redis software locally. And there is our connection by the called Christopher. The name of our connection is R, correct, thank you. So now what we want to do is we want to start storing some keys and values in that using that connection. So of course then the question comes, there has to be some sort of command we can use to say we want to store a value. Well in Redis, and when we're calling Redis from Python, there's a method called set that we use. You just specify a name for the key and the value you want to store. So it is pretty straightforward. So basically in this case, whoops, go back up there. So if you take a look at this, I call my method, my set method. I specify my connection name, which is R, thank you. And I specify that the name of my key is going to be first name and that gets stored here. Or that's the name of my key. And then I specify the value bill to be stored for that particular key. So that's basically going to store this value for me in Redis. And when I want the value back, I can do that by using the get method. So I use set to store a value and I use get to ask for the value back. So when I call the get method, I'm gonna need a variable to hold the value that comes back. So you're gonna see I specify the name of the key, first name, and it says, oh, well, the value for first name is bill and then it takes that value bill and puts it into my variable. That's perfect. So just like we did request form and that stored that into the variable, same concept, you're just gonna say R, get, R, get. And then that's gonna wind up inside of retrieved name. Exactly, except I'm just getting it from Redis instead of requesting it from a form on the browser. Perfect. You can store numbers as well as strings. So absolutely, you wanna do something like keep track. A number of visitors at the website can store zero. It's just by the data type you pass in, whether it figures out you're passing in a string or a number, that'll determine the data type it stores. One of the neat things is if you do store a number, there's some extra methods that you can use to increment and decrement the stored value. Add one or subtract one. Yeah, so if I call increment, it will literally add one to number of visitors, so from zero to one. You can also say increment by, so you can say add five, add two, add six, whatever the number is you need to increase it by. There is also a decrement, number of visitors by one. However, for whatever reason, there's no decrement by. I don't know why, it's just one of those odd little things. So if there is a decrement function, there's an increment function, there's an increment by, but there's no decrement by yet. Maybe somebody will add it in the next version. On it. All right, yeah, if you don't mind, if you could just go that over there. I'll get on that, yeah. You keep doing your thing, I'm gonna start coding over. Okay, that'd be great. Now, Christopher, what do you think is gonna happen if you try to set a key and that key already exists inside Redis? Well, I've seen the slide so I know the answer. But what I would say is, without giving away the answer, when I looked at that, when I look at that, I might think, hey, wait a minute, if the key's already there, am I throwing error? Because I might go, hey, wait a minute, you told me the key value was supposed to be this, now you're telling me a new value, I don't know what to do with this, and it would throw an error. That's it. So there would seem to be at least a possibility here, but I do know what the right answer is. Yeah, in this case, by default, it's simply gonna overwrite. So if I say, because the thing is, when I do an r.set, I'm actually creating the key and giving it a value. So when I call the set function a second time with the same key name, yeah, it might say, hey, that function already, or that key already exists, but in this case, absolutely, it's simply gonna overwrite the existing key with the new value. And this might be the way you want it to work, or it might not be the way you want it to work, just depends on the way your brain works. If you're thinking, no, no, wait, I didn't wanna overwrite what was already there, I wanted to, if it's already there, but I wanna append this value to what's already there, or I wanna get an error message back, because that value shouldn't already exist. So there are absolutely ways that with code, there's always a way, the only question is how hard is it gonna be to check. So there is an exists function that allows you to see, does that key already exist? So I can say, hey, if exists first name returns a true, so if it doesn't exist, well, then let's create it. So if you wanted to add in that functionality of it throwing an error, if it was already there and you tried to change the value, you could do that. Yes, exactly. You just write your own logic. Just write your own logic. Yeah, that's the easiest way to do it. Yeah. If you, now, this is one of those, hang on, maybe this is my side moment. Okay, but I've got to throw them all. Oh, is that the wrong side? Yeah, yeah, so we're supposed to, well, I do it to the right. You have to do it to the left, yeah. So, and then Christopher's off too. I like the fact that Christopher's of Merch's off tangent. One of the things, when I started exploring and first working with Redis, there are some options you can specify when you call the set method, EX and NX and so on. And some of these options say, hey, if you specify this option, it's gonna throw an error if the key already exists. The world of open source code, they don't seem to work in the Python when I'm using them. So I found it more reliable to do the check to see if they exist separately, rather than relying on the EX and NX parameters. But if you read the documentation for the set method, you'll see the EX and NX parameters. You can try them, but I've never managed to convince them to work from Python. So I find it easier to just test for EXS myself. Done with my aside. Yeah, and I would also say, here, I'll go ahead and I'll do this as well, just to continue the tangent. But I would also say that, again, there's multiple ways to write the exact same block of code. And you really do want to prize readability. So I personally like having that extra step, because again, if somebody's never used that Redis API, they go in and they take a look at that, they're not gonna know what NX and NX are. They're not gonna div it, that EX parameter true means if it already exists, give me an error. Exactly, exactly. But if they see explicitly EXS, then they're gonna know what that is without having to know what those parameters are. Absolutely true. So yeah, this is very, it's that sort of, we call it sometimes sort of self-documented code or more readable code. Exactly. This is more intuitive to somebody reading it for the first time. Exactly. Now, if a key does already exist and you maybe want to append to the value that's already there, instead of overwriting it. So maybe people are entering a name and then another name and another name. So maybe your key is called list of names. And you just wanna keep adding more names to the existing list, but when you get the first name, you wanna create it. You can check if it exists using exist function. There is also an append function that you can call which will append a value rather than overwriting it. And that way you really kinda get complete control over what you wanna do with that value if it's already there. Exactly. So lots of options there. If you do want to actually delete a key, go figure, delete. No, I'm sorry, you lost me. Can you do that again? Yeah, I know, it's tough. It's probably because I forgot to do the R dot delete when I started. So if a delete function will allow you to remove one. So let's go to our, back to our treaty application. Yes. And let's see if we can add code. You left me a few to-do items, I seem to remember. I did, yeah, yeah, get to work over there. All right, let's see what I can do. So I'm just gonna, you know, grab my phone. I'm just gonna. Just hang out over there. Get some work done. All right, yeah, sure. Yeah, so going for high scores and word of it, no doubt. So I'm gonna go ahead here and I'm gonna go down, remember, we had some code down here. We'd sent these to the form and then we had, the user had created a question. So they typed in a value. When they submitted the form, it came back, it was posted back to us. That's correct. So they hit the submit button and then we were reading the title and we were asking from the form to get the value of the title they typed in, the question they typed in and the answer they typed in. So what I'm going to do is I'm gonna store it in the data store. Now the variable name I'm gonna use or the key name, just so we can keep this straight, the key name will be whatever title they typed in then colon question sort of thing. So if you think of it this way, let's say they enter a category, it might be music question or it might be countries, can't type apparently, countries question. And for answers, I'm gonna store it with the name something like music answer or countries, again, cannot type, countries answer. So that's sort of the syntax. Though I'm gonna be, things are case sensitive, so I'm just gonna make everything lower case to save myself problems later. I'm always treating everything case sensitive, right? Best practices, music. So the keys are case sensitive. Yeah, so those are the names I'm gonna give to my keys. It'll be like music question or countries question or music answer and countries answer. And then the value will be whatever the user has typed in as a question and an answer. Okay. So I've already created my connection up here, but you'll notice where I had created the connection, I'm gonna actually zoom out on my code a little bit. So you can sort of see this. I wanna point out that this is a function, correct? Christopher, so I have a question for you. If I declare a variable inside a function, where can I use that connection? Inside that function. Can I use it anywhere else? Like in a function down here? No. Right. Only inside that function because it winds up setting what's known as scope. Right. So when I declare the variable inside my hello method for my routing, I can only use it there. So I either have to redeclair that connection for every single function, which is a little clunky. It is. Or I can just take that line of code and move it out of the functions. So have it up here with the rest of my code, not inside the function. Actually, I'll move it up one more line here. So it's above that. And I'm just gonna move that comment up as well. You know what I just did? I just did the cut and paste blank line. Oh, don't forget to put your font back to a regular size so we can see it better. Oh yes, absolutely. We'll do that too. There we go. Move in so you can see it better. There we go. All I'm doing here is I'm moving my Redis connection outside of the function. So above the first function, that way all of the functions in this module will be able to use that code. Okay. So now I have a connection. The connection's called R. And what I'm gonna do is I'm gonna go down to my code. And where you said, Susan, please add code here to store the data in the data store. Add code there. I'm gonna say r.set. And the key name is going to be whatever title the user passed into me. And then a colon. And then the word question. Because this is where I'm gonna store the question. With a silent R, absolutely. And then the value I wanna store inside that key is the actual question that the user suggested we should ask. Okay. Then I'm going to need to store the answer for that question. So again, I'm just gonna use the title that they typed in, which is a category, following my naming convention, answer. Now does it have to be a colon? It doesn't have to be a colon. That's just a convention. If you wanna make it slash answer, dot answer, or you wanna start getting fancy doing title case or something like that, any of those will work. But it's a fairly common convention in Redis. You'll see the colon used a lot. So it's one of those ones, if you start using it, then when you look at someone else's code, you're more likely to see stuff that looks familiar to you. I got you. But no, not required. And I wanna store the answer that the user typed in because remember, little higher up in the code, we had the user had, we'd been reading from the HTML form that question that they typed in and that answer we'd stored those in variables. So I'm just accessing those variables here and storing them in Redis. Yep. So this will store the values. Let's run and see if that actually works. See if my code works. And then we'll worry about retreating. Sure. Okay, so let's execute our code. Yes, I would need to rebuild it. We see the webpage coming up and we go and we decide to create a new question. And because that's of course where my code is written. So I'm gonna write a trivia question on Canada, of course. Let's see, what is our national sport? And the answer? Curling. La Crosse. Actual little bit of Canadian trivia for you. Most people think it's hockey. It's in fact the sport of La Crosse. So I submit that question and we should be taken to the page. It says, oh, thank you for entering your question. What is our national sport? Now one thing that's worth highlighting here is it went to that page. So it connected, did its whole thing and didn't have an error. Now we could have, if we wanted to, add it in the tri block and rerouted to an error page if it would have failed and things like that. And again, it's one of those things where we're trying to just kind of walk through demos and focus in on the mainline code. So that's why we're not incorporating things like that. Could we? Absolutely. But again, we're trying to keep it as straightforward as possible. Yeah, we're trying to keep it fairly simple for now. That way you understand all the basic principles. Now, one of the things we haven't done though is what is our national sport? You had already, that was already done in the HTML. That isn't using Redis. That's not reading the question back from Redis. Correct. So how do we know those values actually got stored? Well, I could start writing code to try and retrieve the values, but then you run into the problem of you don't know if it doesn't work, was the mistake in the code that wrote the values or the mistake in the code that was reading the values? So one of the things that's useful to do is you can actually, when you install Redis on your computer, you get a tool installed on your computer called Redis Client. So if we go back to my computer for a second here, if I bring up Windows and I type in Redis, you can see there's actually another piece of software when you install Redis, you get this included called Redis Client. Mm-hmm. And when I'm on Redis Client, Am I gonna change your color real quick? I'll try to change the values here so it's a little easier to see, yes. St. Via text to black and the background to white. There we go. Nope. Oh, we're good. Okay, we're good. All right, so you can see what we're not sure about. I've never tried to change for Redis Client background before. Okay, now what I can do is those get and set commands, I can use those right here in the Redis Client. So if I can remember the name of my key, and, oh, now I'm just gonna go. Going to the capital C. It was capital C, Canada, and then the name of the question. Then you can see it returns, what is our national sport? So I can see that, and this is, I'm doing this in Redis. I'm basically going to the Redis database and saying, hey, tell me, what's the value for the key, Canada question? Nice. What's the value for Canada answer? So I can see that, indeed, these values are stored. You don't have to be in Python to retrieve the values. Remember, this is separate software. So I can see that they're in there. And, you know, if I want to, I can even try adding another trivia question in here. Let's try setting a value into it. Make it happen. So let's create one called Redis. It's gonna be my category. And the question is going to be, can you store a new question here? All right, and since it said okay, no error message is back, then I'm gonna assume that Redis answer is yes. Okay. All right, so now I've tried using set commands. So theoretically later, when I add the code to retrieve questions, I should be able to retrieve that question on my website. Seems to make sense to me. Okay, so now let's go back to our Visual Studio code. And I've done. Now we're gonna go down here and we're gonna go to where it says, we had the code here where we were bringing up the page and somebody specifies, I would like to see, and when they ask for a question, they specify the title of the question they want. Perfect. Sort of a category, if you will. Don't forget to stop your debugging. Oh yeah, I'm still running my code. Thank you. Yep, I do that all the time. Yes. When we go to that page and they do a get, we obviously have to display to them the question to display. So I need to read that question from a data store and I see a little note here from Christopher. Coming up. There's a code there. I'm back to my phone. All right. And in this case, I need to use a get to retrieve the value and the value I want to retrieve is going to be the key name and the key name is going to be whatever title they typed in because that's gonna be part of the key name. And then we add that colon question and that's gonna shrink. Now we need a variable to hold that value. Question equals. Ah, so basically I'm gonna replace where Christopher had a question is hard-coded question here. I'm gonna say question is equal to whatever is returned from Redis when we ask it to get the value with the key of title typed in. So Canada, Redis, whatever question title they entered colon question and that value is now gonna go into that question variable. Okay. Triple word score. All right, well done. Meanwhile, back at the ranch. And again, we're gonna need, when once they've seen the question and they've typed in an answer then they're gonna post back the form to us and they're gonna give us back an answer. We're gonna need to check if that answer they gave us matches the stored answer. So instead of assuming the answer is answer we're gonna say if the answer that the actual answer is equal to we're gonna have to go get that value from Redis. So we get title answer and that's gonna give me back the answer to the question we just prompted them. And then we have our logic that says if the submitted answer matches that answer then display the page that says you got it right and otherwise display the page that said sorry you got it wrong and make sure you tell them the answer vase was tested and the correct answer. Yep. Okay, so moment of truth, let's try it. And while Susan's bringing this up one thing that's worth highlighting is the way that we built this it was already all set ready to go for that code that Susan threw into there. So we threw in kind of the hard coded values let's go in and test it and then let's go in now and actually start adding on the database code. And this works out well in development because it allows you to kind of segment out where your potential problems are because what we tested originally was the fact that all of our little Python and flash code worked out just fine which was really, really good. And now we're adding on the database part and then we can say, well, wait a minute it worked just fine without the database code now we add in the database code something's going wrong now we know where the problem is or vice versa that if we ran into problems just trying to do it without the database now we know exactly where that problem is and I'm not saying Susan's gonna have problems here I'm just saying it allows us to better identify where that problem came from. And I agree 100% Christopher because you and I both know that as soon as you're trying to create code that connects to something somewhere else to some other application that is often where things go wrong. So it is often the line of code that tries to connect to a database or tries to write to a database or to read from a database those are frequently lines of code that take a little fiddling with to get them working. So that is often where I have problems when I am writing code hopefully not this time but it has certainly been known to happen to me before. Exactly. So what I've done now on the screen is I'm creating a new question in our trivia called and the title is Python and the question is how do you spell Python? And the answer is Python. Python. Right. So I'm gonna submit that question and it says, okay, store my question. Now, if I want to be asked that question we haven't created hyperlinks on the page to take us to that page but if we went back to the routing I believe it was called Question, Whack and then Title. That's right, you type in question and then you type in the title so I called it Python. And that will bring up the question which has that key value of Python. And I go up and it says, now this is weird, we're gonna come to this and just saying this is weird. D colon, how do you spell Python? I'm not sure where that B thing's coming from. And then I type in the correct answer of Python and it's gonna come back and go, ooh. Oh, I think we found a mistake somewhere in our code. Now this may be related to that whole B dash thing. So it's not working yet. And you did see that B popping up on the screen there which is a little strange. Yeah, letter B, letter B. There must be an answer. Yeah, letter B. But if you take a look, if we actually go, this is where having that Redis client is really handy because I can sort of go double check and go, well, did it store the values correctly? So let's go check and let's see if Python question is stored in our Redis data store. Yeah, and it's, there's no little B dash thing in front of it. And if I say get Python answer I can see it is actually equal to Python. So okay, I'm looking at that going, all right, that looks all right to me. What's happening? Turns out if you go digging through some Python documentation and Redis documentation you'll discover that Redis actually stores the key values as bytes, not as a string. So when we do a get in Python and we say, hey, give me back that value it returns it as a string of as bytes. And that's why you're selling the little B apostrophe appearing at the beginning of the string. So what we have to do is we have to tell Python there's two ways of doing this. We can either as we do each get and set we can say turn it into a string and read it back as a string. Or we can actually since everything we're working with in this particular application is all strings. The other option is we can actually specify that on the connection level just encode and decode everything for us treat everything as strings. So that's where I'm gonna change. So we get rid of that B apostrophe and that way when we're doing our gets we're getting a string back and that's gonna help a lot of our code. So let's go back to our Visual Studio and all I need to do is change that one connection string. There we go up here and I'm gonna add two extra parameters here. I'm gonna specify that the character said I'm using is UTF that's when you're changing from bytes to strings it has to know which set of rules to use for the conversion and I'm specifying UTF-8 which just means I'm using eight bits to represent a character. Don't worry about that too much. And then I've got the decode. So I'm gonna specify when I do this please decode my responses when they come back. I would like to do that automatically, true. All right, once I've done that now what I'm gonna do is I am going to stop debugging and I'm gonna create a brand new question. And this time when I go create my new question this is working is what I call it. Does this work? And I'm hoping the answer will be yes. And the answer is gonna be no. Okay, you're gonna tell me why in a second? No. All right, well we'll go this far we'll see where it goes. So we're gonna change this to submit question and we ask does this work and then we're gonna go so we've hopefully got that question stored on Redis now and then we go to question and we bring up the question slash working and this is where I like it's funny I typed it in 30 seconds ago and I'm thinking that's what I typed into the value and there sure enough it brings up the question does this work? But you can see that that B apostrophe has been removed. So I've successfully returned a string now which will be a little bit nice. Now this is where I can see Christopher the smoke coming out of his ears as we're trying to live figure out why we got that error message we were not expecting that particular one. See and you know what all kidding aside here the point that I was making earlier about doing this in phases is really important because I fired up my code that I had prior with just the hard coded little samples and things like that and it's failing there so it's an immediate check to see okay well where's the problem is it on her side or is it on my side is it the database code or is it the original code and it is the original code so I have a problem here with my code. Well I'm just gonna try something I'm gonna do a little of the when all else fails let's see if we can narrow down where the problem is so which is a popular programming trick so what I'm gonna do is I'm gonna it was the answer was correct so what I'm gonna do is I'm gonna say if a submitted answer equals answer I'm just gonna return correct is that work? No, okay. Yeah it's failing when you hit submit so it's actually not even it's not even hitting back into the server which is really weird. Oh so the post isn't working. All right because if I put the break point so if I put a break point here we're not seeing it go to this code. Correct. Okay. Yeah. Ah. All right well I'm going to well just to sort of demonstrate cause we did actually have a request earlier of can we show how the debugger works so I'm just gonna put a couple of break points here so we can kind of see you know this is what I would be doing to try and figure out what's going wrong with my code I'd put a couple of break points in by put you just click in the margins there and you create those little red dots in the margins that creates a break point and that's a way of telling Visual Studio when you get to that line of code stop so I can please look around. So if I run my code now. Oh, okay. Got it, okay. Just a second let me go and I go in and I launch my application and this time I'm gonna jump straight to the question because I know that's where my problem is so I go to my question working and you can see it doesn't bring up the website instead right away it brings me back to my code because and you can see a little yellow arrow there and that little yellow arrow is indicating this is the line of code that's about to be executed. So you can see that it's about to see if the request method is a get and what I really think is cool is the way when you hover over things you can even sort of get a preview of what the different values are which is kind of cool. So now I can use these little buttons in the very top corner to step through my code so step into sort of gonna execute one line of code at a time. So I can execute a line of code and I can say okay so obviously the method was a get because now it's going to go get the title and I execute that line of code and again it's neat if you hover over the variable oops I'll have to do that in a live preview. Then what's neat is when you hover over it you see a little pop up that tells you the value of that variable so I can see as I'm stepping through my code that the value of question is currently does this work so I can see that working and I know that that line can be executed successfully. And now I can see that the yellow arrow is on the return statement so if I continue it's going to bring back that template and I'm going to see the page asking me the question. Okay now do me a favor go back to the page that's asking you the question don't close that just go back to your browser. And I was on this one here I've got too many windows open got to find the right one here I was on this one. Okay so you'll hold on one second so you'll notice it says does this work. Well one of the very cool things about the way that our templates work is that we can actually make changes to the templates without having to recompile our code. So here's the problem go back to Visual Studio. All right so okay so we've been going through the bugger the blogger's brought back to find a high I think I know what the problem is. I know what the problem is. Okay and are you about to try and fix it? Yes. Okay so now this is another neat feature of the debugger in Visual Studio the fact that if you think you know what it is you can fix it and keep going. You can fix it in certain places you can fix the template your Python code you're not going to be able to fix but your templates you are. Now what I want you to notice and this actually goes all the way back to earlier this morning when we were talking about creating those forms and reading the values in and we talked about keeping those values in sync. And I will always admit when a demo failed that I wasn't expecting because there are times when I'm expecting a demo to fail. Yeah sometimes we yeah absolutely we both do that. So in this case that's not what's happening here. This I was not expecting but it's a perfect example of that trying to keep everything in sync. Now one of the things that was happening is I was doing my demo sort of in chunks that I went off and I did my form back and I did my code. So you'll notice there request.form submitted answer. So down right at the very bottom the last line of code you got. Yeah so you'll notice right there that it says submitted answer request.form submitted answer. Do me a favor go into templates. All right let's go to the templates and then go into answer question. Into answer question. All right. And now scroll down just a scooch perfect and then you'll notice input type equals text. Yep. And then name equals and it says answer. What was it expecting. Something else I'm guessing. It was expecting submitted answer. Submitted answer. So what we can do is just update that. Submitted answer. Nope. Was it all lower all lower case. Camel case. Camel case. Lower case lower case. Lower case S. Lower case S. It's specific thank you. There we go. Camel case. And so now go ahead and save this. All right I can never remember which is camel case and which is path. That's okay. Good save. And now go back to Internet Explorer. All right so this is a case where it's interesting. Remember right I'm still running the application this whole time I've still been debugging. So this is a live change. Instead one of the cooler things about Visual Studio is that sometimes you can do this. So yeah going back to my page. And then now go ahead and type in whatever it is that you want. Yes. Perfect. And then now go ahead and click submit. And so you'll notice that it will now actually go back to the debugger. And one little thing I'm actually gonna kind of keep going here. One thing that I sometimes find is I'll go in and I'll set a couple of break points and then I'll realize okay wait a minute. You know what I figured out what it is. I fixed it. Just go. Engage. Finish. So one of the cool things that you can do is you can actually just click continue. Yeah. And it will just either go to the next break point if you have one or it will just run the rest of the code. So hit continue here for me. And in this case I expect that to run till it hits another break point. Now I do have another break point back here. So it was okay. Then take away that break point for me. It's okay to show it going through. Okay. So there's our little break point. So you'll notice that now it's actually going to read the answer correctly. Yeah. And if I execute that line of code we should it should go through and do that successfully. Yep. So if you mouse over submit an answer. Yep. If it's still in. It's still over in the world of HTTP. Yep. Okay. No and I'm still getting a bad request there. All right maybe I don't know what the problem is. It's going to be something along those lines. Okay. So if I put a break point here and then I should be able to get it to continue but yes I'm still getting my bad request back. Then let's do this. Let me finish talking to Redis. And what we will do is during the debugging and figure out it is. But you can see where that debugger becomes really valuable as a tool as you step through your code and try to find things. And you also see that yes no matter how hard you try it's very easy to mix up the names of your variables from your template to in your forms when you're back and forth from Python. So change a little bit, test it, change a little bit, test it, change a little bit, test it. The more you do that the easier it's going to be to find your mistakes when you do make them. So we know it's not working yet. I'm just going to stop debugging and go back to the slides for a minute. So we were able to save and retrieve some values of Redis and we were also getting rid of that B apostrophe by adding an extra parameter to our connection string. When we say decode response that equals true and char set equals utf8, that allows us to get rid of that B apostrophe that appears when we're storing the values. And we already demoed how to do that. So we do want to pick up some good habits early when we're working with Redis. I said we'll generally use a hierarchical naming convention for Redis keys, much like we did here, sort of question title, colon question, pair a game, high scores top, user one, two, three, four, five, name. Those are sort of typical examples. You don't have to do this, but it's a convention that's useful to adopt and it's fairly widely used. A couple of FAQ. I know the first time I was opposed to Redis I was sort of like wondering, huh, if I store a value in Redis and then I leave the website, will that value still be stored when I come back? Because when we were working with variables, if you declare a variable in your Python code, well, when you leave that website, that variable value's gone. Well, what's different about Redis is we were looking at how Redis is completely separate. We were able to access the values over here in our Redis store. So in this case, yes. If you go to a website, you store a value in Redis and then you leave the website and turn off your computer and come back three days later, that value's still gonna be stored there because it's a data store and that is its job. It's to store that data until you tell it to get rid of it. Now, it is possible if you want to delete the key. That's one of the reasons that's useful. There's another option as well. If you just take a quick glance down at the slide, there is an expire function you can use as well. So if you know you don't want the key to stick around for too long, you can actually call r.expire, tell up the key name and how many seconds you want it to stay alive. So it is possible to create, if you will, temporary storage. Next question, if I have all sorts of users visiting my website, are they're sharing the same keys and values? And again, the value here is yes. Redis is a data store that's separate from Python. If Christopher sets up, runs this website and he's connecting to my Redis data store, then when he tries to look up a value, he's looking at the same value that I stored. So we're sharing the same data when we use a data store. And again, that's a little bit different from when we're working with variables inside our Python. You can do a lot more of Redis than we covered here. This is, you know, intro to Redis. Enough to get you started storing values, retrieving values. If you want more information, here's a couple of good websites that you can reference. Yep, okay. Let's give it one more shot here. Got an idea? Go back to Visual Studio. All right, Christopher, thanks. You got a shot at how to fix it. Do you want me to get rid of my break boys? No, it's called out for me real quick. Okay. SCB, yep. Okay, go back to answer question. Go to the answer question. Answer question HTML. You want me to go to this particular template? Yes. All right. So I'm going to go to the answer question, HTML template. So that's in my templates directory. Answer question. Yep. S-U-B-M-I-T-T-E-D-A. Okay. You want me to just cut and paste that variable name and bring it over? Sure. I now know it's correct. What I actually want you to do is just run it again. Okay, sure. So just, yeah, launch it one more time. And if it fails, then we'll go back and fix it. You think it might just be the case if a live update wasn't enough? Yeah, sure. If the live update just didn't work. That's possible. Everything lets you do live updates. Actually, I don't want to do a create. I want to go to a question. Yep. Let's go to question working. All right. Does this work? Hoping the correct answer is yes. We will find out. Submit. And the answer is correct. There we go. High fives. All right. So I want to do two real quick things here. First of all, I want to talk to the problem one more time just because I want to make sure that we know what went wrong here. I can review that. Since I have the Visual Studio open here, it's probably easier for me. Sure. Go for it. OK, so the problem we had was inside of our form, answerquestion.html, we had created a text box. And the name of our text box was Submitted Answer. Though originally we had that name set to Answer. Correct. And then in our Python code, when we went back to our Python code, we had said, hey, go to the form and request the contents of the variable Submitted Answer. And originally in the form that was called Answer. Exactly. So we had two different names there. One was Answer. So it was kind of like we had it like this. Exactly. So when we went, so when Python said, hey, form, give me the value of Answer, it said, never heard of it. And we changed that and make it the correct value of Submitted Answer. It says, oh, I have a text box with that name. I'll give you the contents of that text box and put it into this variable. That's exactly it. And then the second piece of the puzzle. The second thing, well, that was the problem. That was what caused the error. Now that we actually have this working, I want to go back and do something here. So go ahead and hit Play again for me. Sure thing. Just because I want to prove that our data is actually there. So do me a favor, go to WAC question. Yeah. WAC Canada, capital C. Sure. Go to my Canada question. Yeah. And you're going to notice, there's Canada. So what's our national sport? Type in curling. I know what's wrong. All right. Curling. I was going to go with hockey. You know, I am hockey geek girl, but OK. And hit submit. And sure enough, you'll notice it tells us we're wrong. And you'll notice that it pulled the cross out of the database. So even though we shut down the app, open it back up, shut down the app, open it back up, Redis is a separate service. So all of those values are still there. So if you also went in, and I think you called the one that you created through the command line, Redis. Yes, I did. Oops. There we go. And you'll notice, can you start a question here? You'll notice that, again, she created this through the command line. You can see that right there. So even though she created it from there, it's stored inside that database. Our app is now just another client over that database. So even though we kept shutting that thing down, opening it back up, shutting it down, opening it back up, all of the data is still there. The flowers are still standing. So what we now have is that front end to that database. And that database is a separate service. Yeah, exactly. So you can really see the separation of the database and the Python code. So it's really a different concept, different thing to work with, but it adds a lot of power to your applications to be able to store things between users, across users, and across launches. Exactly. We're all the story. Make sure you have your names right. So, Susan, besides having our names right, what did we learn? Basically, we learned how to store and retrieve values in Redis, and how you can either overwrite existing values or append to existing values, delete, expire, and how to debug our code. Is it turned in? Yay! What can we do with this? We can do things like track number visitors to a website, store high scores for game, remember user preferences, remember information about a user. Really, whatever you need to remember, you can store in there. It's pretty cool. So I'm just going to laugh at our little mistake, turn a little red. Go on live. That's what I do. Absolutely. See, we're really cooking here on this show. And, you know, speaking, again, you know, there's another brand new poll that's going to be thrown up there in a minute about the closed captioning. First time ever that we're doing that, please answer. And then, what do you say we take a break? We take everything that we've done here and make it available. Right, because right now, you guys can't actually try our website. It's not possible. Exactly. So we should allow the world to use our website. Let's foist it out there. Yes, so we're going to talk about how you deploy this so others can use the awesomeness of code that you create. But first, 10 minutes. All right, see you soon. I'll see you guys soon. Do you have any 10s? No, no 10s. Go fish. All right. OK. OK, we're good. Sorry. All right, OK. OK, so pass it over. Yeah, clean that up. OK. Hi. All right, hi. Yeah, so that's Susan. I'm Christopher. This is an introduction to creating websites using Python and Flask. And yeah, so where we left off, besides a little bit of troubleshooting, was we left off with finally the ability to store all of our data, all those put away. Those are all put away. We're good. Perfect. The ability to store our data inside of a database, but we've still been doing all of this development locally. So unless we're going to grant everybody the ability to connect to Susan's system over there, nobody else is going to be able to see all of the great work that we've done on this application. So now what we want to turn our attention to is taking what we've done and sending it out to the world. Because after all, the title is Introduction to Creating Websites. So it's right there in the title, Web. We need to deploy this out to the web. And that's what we want to take a look at. So we want to see how we're going to take Flask and Redis and put this onto Azure. So to put together our Purpose slide, we've been building this wonderful website. And now we'd like to share it with the world. How are we going to do it? Well, we've got to talk about Azure. So we're going to talk about our Azure accounts. We're going to talk about Redis and Azure. And we're going to talk about Flask and Azure. Now, as far as the Azure accounts go, one very big thing to keep in mind, and you're going to notice the slide here mentions a 30-day free trial. But it's worth highlighting, besides the free trial, that there's a lot of ways that you can go get Azure credit. So for example, if you have an MSDN account, depending on the level of account that you have, you get a certain number of dollars. And I want to say it's between $50 and $150? Typically around $150. So typically what will happen if you're working at a big company, there's a very good chance that your company has some sort of MSDN agreement with Microsoft. And generally, those agreements often have an Azure component included. So if you're working at a big company, it's worth going and talking to whoever is your IT person who works with your licensing and finding out if you have some Azure benefits. If you do, then you can literally sort of connect. What you do is when you create your Azure, it'll say what subscription do you want to use, and you point to your company's subscription. And then basically it comes off your company's Azure credits. We also have a program called BISPRK. So if you're starting up your own company that is going to be creating and selling software, things like apps and so on, you can apply for the BISPRK program, which will require you to have a website. So that'll be a nice little requirement while you're applying for your BISPRK. You can use Flask. Exactly. And when you're accepted into the BISPRK program, you get an MSDN subscription. And that particular level of subscription gives you $150 a month worth of Azure credits as well. So there are certainly a couple of different programs that can give you access. There's also if you are at a university, if your professor wants to, if you're learning Python and Flask in a university class, your professor can actually request Azure passes for all the students in the class. So if at all the students in the class can go ahead and try out Azure and they again get about $100, $150 with free Azure a month, and that's valid for about six months. So it was a lot of different options. You moved that much too fast for me, although I guess maybe you were just perfect timing. Just as you started that, somebody posted in the Q&A, maybe a good question, is there DreamSpark Azure credit? There is not a DreamSpark specific Azure credit. I can promise you that something we're working very hard on. I actually work with DreamSpark. I work with students as part of my job as a technical evangelist. It is something we're discussing with the Azure team right now, saying, hey, how do we work this in so that there's an easy way for any students who have access to that DreamSpark program that gives them the free software to try and include Azure in that. So that is something we're actively working on, but nothing right now. Okay. Now one thing that is worth highlighting about those different credits is that they're based on a dollar amount and the reason it's based on a dollar amount is because there's a lot of different things that you can use Azure for. So you can create websites, you can create Redis, you can create SQL, you can create VMs, you can set up virtual networks. I literally have a slide when I do Azure presentations, but it has 200 icons, and those are all different things you can do with Azure. So we're going to focus in on two of them here. Yeah. We're going to focus in on two of them. But the reason that's why the credit is X dollars because we have no idea when we give someone credit which of those services you're going to want to try. Exactly. So you have the full flexibility to do whatever it is that you want. But yeah, let's show them how, let's show them the Azure features that are going to be able to allow them to put Redis and Python Flask on out to the world. Yeah. We should also highlight that you can get a 30-day free trial as well. Anybody can get a 30-day free trial. Yeah. Anybody. Yeah. Credit card is required, but you can set it to not be charged. So that way, if you overrun your credit amount, you overrun that 30 days, that your credit card is not going to be charged. I think that's a default. I'm not 100 percent sure, but I think that's actually, there's a little checkbox sort of thing when you're creating your trial account that basically says what do you want to happen when you run out of credits, and you can choose start charging me or shut down my service. So if you're literally just playing and trying it out, you can do it at zero risk of being charged. Yep. Now, let's focus in on Redis first and Azure. Now, in order to create a Redis cache, unlike before where we had to download that and install it and start the service, now we can actually do this through the UI, that and this is showing the cool new portal, which I love, where you just simply go in, you hit new, and then you hit Redis cache. It will then prompt you for the name that you want to use. It will prompt you for the subscription that you want to use because you can have multiple, maybe Visual Studio or an MSDN subscription like I've shown here. It could be one that you're paying for, different options that are available. You get to choose the location where that's going to be stored. So obviously choose something close to where you happen to be or where you have application. Where your users are going to be. Yeah, happens to be hosted. And then finally, last but not least, is that pricing tier, and that's going to control the amount of storage space that you're going to be able to have. So shall I go ahead and show everybody how to do that maybe? Sure. Because you've got some slides there, but let me jump ahead and actually flip over to my system. What I've done is I've gone here, and if you take a look at the URL I've gone to, it's portal.azure.com, and that takes me to the new Azure portal. And when I go to that portal, I've logged in with my Azure account. And what I can do is I now want to create a new Redis cache on Azure. So I go down to the bottom of the screen there, and there's a little new button. And when I click on that new button, it gives me the option to create all kinds of different things we were saying. There's lots of options. You want to do Buntu server? You got it. You want a team project? You've got it. You want a new Relic APM? Got to say, never even heard of that one. You can have that too. But if you scroll further down, you will see one of the options is indeed the ability to create a Redis cache. So I'm going to choose Redis cache, and I'm going to get a bunch of prompts, ask me what I want to call it. Now, if you remember, when we connected to a Redis cache, we specified that we were connecting to local host. Well, if we're going to put our Redis data store out in the cloud, we're going to have to specify the server name to point to that Redis data store out in the cloud. And that's where this DNS name comes in. The name I type in here is actually going to affect the name of a server I type in when I want to connect to it later. So I can call this my flask, flask test, rediskash.windows.net. So, whoops. Sorry. One of the things is it all has to be lowercase letters, no spaces. That's why I'm getting a little explanation mark there. Oh, that name must be used, doesn't like it. Flask test is, if it says that name is not available, remember, this has to be unique around the world, so it means you've got to come up with a name. So I'm going to call it my MDA on... Lowercase. Yes, lowercase. MDA, flask. It gets me all the time. I always want to do camel case or pass count. Pascal, yeah. How about MDA, Flask, Python 2? Are you happy with that? No? I'm happy with it. OK. How about sues awesome DB? Yeah, happy with that one. I think you're limited to the number of characters. Yes, I think I've got too many names. All right, how about short name? It really doesn't like it. Just go with short name. My name. Use at least six characters. Is. It's being really difficult. It's funny. I've actually got one already created, and I don't know what's going on, but it is being ridiculous. It just doesn't. That's OK. So you'll notice here that you can go in. I'll go select the rest. Don't worry about it. So I can pick the pricing tier. So the pricing tier, in this case, for what I'm doing is a very small database. I'm going to be fine with the basic tier, which is cheaper. It's going to use up my credits less quickly. So I'm going to pick the basic tier, and I'm going to select that. Then the resource group, you don't change that. That's used when you start setting up for high availability. Again, for subscription, that's where I would, if I'm working at a big company, maybe they have a subscription I can use. In my case, I have a subscription I have. I have an MSDN subscription, so I pick that. And that determines which subscriptions, credits, or billing would be hit. And location is, which physical server in the world is my Redis data store going to be stored on? Now, I could store it on Japan if I want, but if the people who are going to be using my website and storing values aren't living in Japan, I'd probably want to pick something a little closer to home. Probably. So I live out in the East, so I might actually pick the East US, because I live in Ontario, and that's actually reasonably close to where I live. So that literally determines a physical location where your database will be. You want that to be physically close to the users. And then when I'm done that, I would literally just click Create, and it's going to go off and set that up. Now, I'm not, it's okay, I'm not that concerned about the fact I'm having problems with the DNS name, because it takes about 10 minutes or so for it to create the Redis data store. I'm not sure why it's so slow, but it takes quite a while. So a lot of people will say that, you know, that it takes a little while for it to do it. But what I always like to say is, think about what's happening here. Now, what this is doing is this is going off and setting up a database server that's going to be globally available to anybody that you decide, or any application that you decide to have access, it's now going to be globally available. So it's gonna take a little while, absolutely, but it's actually doing quite a bit, and it's still going to be faster and easier to maintain in the long run than if you went off and tried to do it on your own. So, you know, does it take a few minutes? Sure, absolutely, but you know. But it beats having to buy my own server, install it, connect it to a network, install Redis on that so everybody can access it. And by the way, I found a name it was happy with, so it's now going off and creating my Redis cache. Perfect. Once I've created the Redis cache, what I would do is I would simply, when I'm ready to go back to it, I would go to browse. Yeah, show us the turkey in the oven. Yeah, and you can actually see, if I can get a list of all my Redis caches, and you can see the one I'm in the middle of creating called Sue's Redis cache. That was the name I was finally happy with. And show us the one that we're going to be using. Yeah, so you don't have to wait. We've got, said the turkey, over here, we have our completely turkey. And it's from those great cooking shows. And now when I select it, I can look up some important information I'm going to need when I connect. So let's say I've forgotten that URL. So I don't, instead of local host, I know I need a different URL, but I can't remember what it's called. I can simply go to properties and over here, you're going to see the host name. So that's what I'm going to type in here. That's going to be my host name instead of local host. Now here's something really important. Notice the SSL port. All the examples we were doing earlier, we were connecting with port number 6379. One of the things about working with the Azure Redis cache is by default it uses SSL, which means it's encrypting things and trying to make sure people aren't sort of looking at your stuff as it's going across. Exactly. Yeah, just a couple of other really cool things as well. Also make sure that you're connecting to the system that you think you're connecting to. Because if I'm using this as a backend database and I've got my application and my application makes a call into it, I want to make sure that I'm calling into the right database and I'm not calling into maybe a server that's trying to spoof the one that I think I'm connecting to and now all of a sudden I'm putting sensitive data into the wrong place. Into somebody's database who's trying to steal my data. Yeah, exactly. So SSL is more secure, but it does use a different port number. So we're also going to have to change in our connection string. We're going to have to make sure the port is 6380 as well. So that's a couple of little things we need to know. Now the other thing is when you are using SSL, you'll also be required to pass it a key. This is an encryption key that's used. So how do you find out what the key is for your cache? Once again, if we take a little look here, you can see there's a little button up here called keys. If I go and select that button, it will actually bring up a primary and a secondary key. You can't see the entire key. So you won't be able to just zoom in here and steal my keys. But what you can see here is there's this key here. You can use the primary or the secondary. And what's wonderful is this little button here. If you click on that, it will copy the key. So you can just paste it into your code. Because you're going to need that in your connection string. You don't want to be typing in lowercase k, lowercase x, lowercase m, uppercase l. The odds of getting that correctly are pretty slim. So that little copy button is very useful. You're going to need that in your connection string. That's going to be the password value. Yep. So that's how you create your Redis cache on Azure. And that's all the information you're going to need about your existing Redis cache so that you'll be able to connect to it from your Python code. So shall we see if we can actually update our Python code to now connect to this Redis cache? Sure, it sounds good. So let's kind of walk through what we're going to need again. We're going to need the URL that we're going to connect to. We're going to need the primary key. And then there's the updates that we need to make. So we need to go in our DNS name, Redis cache, Windows net, our port number 6380. Now, one very cool thing again, since you're using the key value pairs, is that we can reorder things. So you're going to notice when I go back to my code that I put the SSL there. Because we've named the parameters, it doesn't matter. Exactly. And since our database isn't going to change, we don't need that. And then I just don't want to put the password down on our screen. By the way, you are going to notice, yes, I'm going to check this code into our GitHub. And you're also going to notice that we're going to destroy the cache right after creating this MBA. Because I'm not going to have you guys all run up my Azure bill. Yes. So anyway, so. By hosting all your websites with my Azure cache. So what you're going to notice, let me come back over here to my code, is that there's my little update. You'll notice there's my host. There's the port number. And then you'll also notice scroll over a little bit. And there's that SSL equals true. And that little thing is going to make sure that it's going to use SSL. It also tells it to use port 6380. That sort of reinforces it all. Exactly. So now, let's take our Flask app and actually port this out to Azure. So let's start off by talking a little bit about what an Azure site is. And put simply, it's hosting for web applications. Does that slide say MVC? No. Does it say web forms? No. Does it say a node? No. Does it say PHP? No, it just says web. Web applications. Completely whatever technology it is that you want to use. So if you want to use MVC, if you want to use Node, if you want to use Flask, if you want to use Fill in the blank, we can host it. So that's the great part is that it doesn't matter what technology it is that you're using. The next big thing is that Azure will scale. So if you want to just go in and create a little test site, you can do that. If you want to create a full enterprise application that's going to scale, have global failover, and the whole nine yards automatic backup, you can do all of that. So you can start very, very small and grow this out to very big. Now, of course, the next question then becomes, well, how much is this all going to cost? Now, the cost of the pricing models, the levels, are going to indicate the different features that are going to be available. So whether or not SSL is going to be available, scaling is going to be available, automatic backups, the ability to do deployment from dev staging to production, and so forth. All of that is going to vary based on the pricing level. And again, we need a T-shirt. There's an MBA for that. I do want to highlight that coming up January 14th, that we are going to have an MBA on beginning Azure websites. So if you want to see the power and capability that Azure websites has to offer, come join us on the 14th. You can check all of that out. Now, for our purposes, we've got a very simple lap here. So we're just going to go with our free websites. And our free websites are a perfect little playground. Yeah, they really are. Exactly. Playground's a perfect word for it. It's just a place you can go. You want to explore, try putting websites out in the cloud. And the cloud is one of those buzzwords these days. You are going to be dealing with the cloud. So you've got to start learning it somewhere. Exactly. And so you get up to 10 of these, but keep in mind you're only allowed five concurrent connections. So again, it's a playground. It's just some place to go off and poke at things and just kind of see, all right, well, what's going on? Well, let's go in and see what's going on. Now, Susan did everything through the Azure portal. And that's cool. And I love the Azure portal. And it's a fantastic little tool there. But here's the thing. I'm in Visual Studio, Susan. I want to use Visual Studio, Susan. Yeah. Can I use Visual Studio? Yes. Call all. Which is awesome. All right. I'm just going to use Visual Studio. One less interface to learn. Exactly. So I'm just going to right click here. And I'm going to say publish. And it's going to say, all right, well, choose your target. Microsoft Azure websites, or importer custom, and a whole bunch of other options. In my case, I'm going to go with Microsoft Azure websites. Click. And now it's going to say, all right, well, sign in. OK, well, let me sign in. And let me just go ahead and cause a distraction over here. Yep, hi. Causing a distraction. Yep, yep. That's a distraction. Barry, Barry, distraction. Distraction, oh, wait, so this is a part where Susan says, so meanwhile, I was talking earlier, one of the things I'm going to throw into the QA window, we were talking about ways to access Azure. I'm about to toss up in the Q&A window if you link for where you access Azure Education Grants, because I was mentioning that ability to get the free Azure for anyone teaching courses, which is really popular because, say, you want to try web hosting and you want the students to build websites and deploy them or try storing Redis on Azure and so on, we do have those great educational grants. So I'm going to put that into the chat window in case anybody's looking for it. Perfect. OK, so now, back over to my system, now you're going to notice that I can deploy this out to a little site. You'll notice we have a little last minute test that we had from the other night. I'm just going to go in and click New. And it's going to say, all right, well, give me the name of the site and let's say MVA Flask. It's green. The subscription, I'm going to go in with Visual Studio Premium. It's going to ask me for my region. I'm going to go with West US. It's going to ask me for a database. I don't need a database. Because we're going to wind up calling Redis as a cloud service. So I don't need to create a brand new database here. So that's it. That's all I have to do. And then click Create. And then just a little back and forth here with a little green. Waiting, waiting. There I go with the little dance again. All right. We're waiting. We're waiting. We're waiting. Now again, people will look at that and go, why is it taking so long? Think about what it's doing. Yeah, it's still a lot simpler than going out, purchasing a server, bringing the server home, installing an operator system on that server, installing IIS on that server, configuring it, and trying to set up all the security for all of that, and then figuring out how do you deploy your website to that server that you just bought and installed and did all that work on? Exactly. I get better things through with my time. It's football season. You know? All right. Hockey season. Rabbit season. So now that this has come up, I'm now going to just simply hit Publish. That's it. And so now what it did is it created a free website for me automatically. It is taking all of my code here. It's packaging it all up. And it's sending all of that up to our little MVA flask site. And in about another 12 seconds here, it's going to pop up a copy of Internet Explorer that's going to show me the website that we have created. So I'm just going to wait, wait, wait, wait. Again, moving the mouse. And you'll notice sure enough, there's a little create a question. So I'm going to click on Create a Question. And this is going to be Azure. And can I create free websites? And the answer is yes. I'm going to hit Submit Question. It created it. And then I'm also going to go in. And I'm now going to say forward slash question Azure. Enter. Can I create free websites? And the answer, of course, is yes. And hit Submit. And all of this is now done on the cloud. This has all been deployed out to Azure. And the couple of things that I like here is the fact that this is so much simpler. And I know we've been sort of beating this into the ground. But it is worth highlighting one last time. And I promise this will be the last time. This is so much simpler than going off and having to set up a server on your own. And you'll notice that Visual Studio tooling here is pretty impressive. So when I was ready to deploy out my website, I was able to just do that straight from here. And you would also notice that if I went back into Visual Studio, I made a couple of changes. Imagine I made a couple of changes. I go in, I make a couple of changes. And I'm ready to push these out again. It's just as simple as right click and publish. Cool. Doesn't matter if you're doing it locally or if it's out on Azure. When you say publish, it sends it to wherever you wanted it sent. Exactly. That was pretty cool. That is pretty amazing. I mean, literally, we've taken that website, but we built from scratch. And you know, if somebody- There's really only one error. And you know what really blows my mind, boggles my mind is I have to admit, if somebody had told me two years ago, I'd be doing a Microsoft course showing someone how to deploy Python and Redis onto Microsoft Azure, I might have thought they were nuts. I got to say times of change. It's kind of cool that we're sitting here doing Python and Redis, which are open source technologies. And putting them out there on Microsoft Azure. You know, I have to say, kind of just following right along with that, is that I've been a Microsoft guy pretty much through and through since about NT4. I actually got my CNA on Network 312. Again, I'm dating myself here. But since NT4, I've pretty much been all Microsoft. I had a little bit of a tangent with Linux. I did Linux for a little bit. Just kind of played around with it. I did just enough cold fusion to be dangerous with it. But outside of that, it's been Windows, it's been SQL, C-Sharp, web forms, and every other Microsoft technology. Do you wanna know when I started getting into and doing open source? Are you ready for this? When I got a job at Microsoft, true story. So it's a very different world. Now, you don't have to publish your websites to Microsoft Azure. There are other places you can host websites. Said, Azure is one of the great places to store it, but certainly that's not your only choice. You can absolutely do research on other web hosting options as well. But yeah, the Azure is very easy. It integrates really well with Visual Studio. And there is a support for Redis on Azure as well. So it was a nice example of a place where you can point everything. Yeah. So with that, the big thing to highlight now to everybody, I don't have a slide unfortunately of what did we learn and now what can you do with this? Well, what did we learn? We learned how to get in and start working in Flask. So we started off kind of talking about the basics of Flask. We rolled that into setting up our templates and detecting the request types and responding to it. Then we added on a data store and closed all of that out with publishing. And that really is, that's the core toolkit that you need to create any type of application. So you now have enough that you could go off and create some simple applications. So maybe you needed to set up something to do polling. Maybe you needed something to... Maybe you're setting up your own hockey pool. Yeah. So kind of thing. That kind of stuff. Absolutely. Sorting the schedule for your volleyball team. Absolutely. And people can report their game scores at the end of the games if you're keeping track of a sports league. The way that I learned ASP, and this was again years ago, but the way that I learned ASP was actually going off and creating a website for our fantasy football league. There you go. Yeah. Because it doesn't matter what you're doing to practice as long as you're exercising the muscle. Yeah. That's the important part. Well, with that, what do you say we call it a day here? I think we've done a fair amount here. So a couple of real quick things. Number one is you're gonna notice a little poll down at the very bottom. Please do go ahead and answer that poll really quickly. Number two, do thank everybody for tuning in. Hopefully you guys had as much fun as we did. So are we done? Arrr. Arrr. I believe we are done. No more iPads just required. And I wanna thank everybody for joining. Please check out the couple of next Web Wednesdays. I believe the next date that we're back is January 14th on a Web Wednesday. There are other MVAs between now and then. Susan, again, always a pleasure. Merci, vielen Dank. Auf Wiedersehen. Ciao. It's been awesome. And so long. Konnichiwa. Thank you very much.