So now we're going to solve the problem of a POST followed by a refresh. And we're going to use something we've talked about before. We're going to use a redirect, right? So the basic rule is, never send HTML as a result at the end of a POST request. In a sense, if you're going to return something at the end of the POST method, return a redirect. Don't return HTML. Now, we've got to eventually get them some HTML, so we redirect to a page that we know. And then that will cause a GET request, and then that page is what we will show. So the question is, handle POST, send a redirect, and then redirect to where? Now, this is kind of controller, right? We talked about model-view-controller, right? Controller is oh, something happened and I'm going to move the user's browser from here to here. So redirecting, when we're redirecting, in a sense, that's a controller function. So we often do our redirects from the views. We're saying here, we're at the end of this view, you know what? I don't actually want to show you a page right now. I'm going to send you to another page, so that page you see with a GET request. Now we often send ourselves back to the exact same page. We take a POST on a page, and then we redirect right back to the same page. So to remember, we've got 200 OK, which is a nice page. We've got 404 Not Found. We saw 403 Not Authorized before, and 302 is Found and Moved, and we're going to reuse this redirect capability. But we're not going to do a wild redirect to a site completely outside of our site. So this is a diagram from Wikipedia that's talking about the POST redirect. And on the left side, we have the problem where the user fills out some kind of a form, does a POST, changes the data in the server. We send back a 200 request, says your order was successful, and then the user hits the Refresh button. Now the key is, this only happens if user hits Refresh. And then the browser asks, are you sure you want to do that? And if you say yes, then it's going to order twice, or deduct the database twice. So the solution is for us to have the user fill out the form, click a Submit, send a POST request. Do the actual transaction, insert an order, or do whatever. And then send a 302 redirect, and then the browser instantly goes blink blink blink. The browser instantly turns this into a GET, potentially right back to our same page. And then we send the page back that says your order was successful, or whatever. And then if the user refreshes that, it just says over and over your order was successful, okay? Now, one of the things we're going to also show you, when we do this, is that we might actually have some kind of a message in that moment of POST, because that's where we got the POST data. And then we've got to pass that to the next request, and we're going to use the session to do that, and then the message can come out. So this whole your order was successful, often it knows the order was successful in the POST code. So we have to send this to the next request, and we use the session to get it from the POST request to the next GET request. And that's a technique called flash messages. And I'll show a simple way of doing that. And then later, we'll show a more complex way to do this Django style. Okay. So here we go, this is actually the nice way to do this, right? So when we first go to the page, we're going to go to a GET request. We're going to see if there's the message. That's that incoming message. But it's the first time, so there is no message. We'll talk about that in a second. If there is a message, once we've got it, we're going to delete it from the session. And then we're just going to send the guess.html with the message. But the first time through message is false, so you'll see no message, right? So the first time through in a GET request, it runs this template. There is no message. And then the CSRF token is there, and so we get to see that as our GET request. Okay? So that is the GET request. So we then put in our guess, and then we press the Submit button. That gathers all that data up and sends a POST to the browser. And so that POST will end up after CSRF checking will come here, because it's a POST. And so what we're going to do is we're going to grab the guess, which now is coming from the POST data. We're going to check it. And message is just a message of too high, too low, etc. And now, instead of rendering, which is what we did before, we rendered right here. We're actually just going to set that into the session under message. We're going to store it. And then we're going to send a redirect, and we're going to send a redirect to request.path. Which means that we're actually telling the browser to do a GET request right back to us, which means it's going to come in here. Then it's going to read the message, and then the message is going to come out here. Okay? So that's how the POST happens. Let's go through that again. We get the POST, we grab the guess, we check the guess, and we store our response to the guess in the session. And then we redirect back to ourselves, which comes into the GET. We pull the message out of the session. We delete the message from the session, and then we actually render the page. So you get the original GET request, you type in your guess. Hit the Submit button. Went to the URL, awesome. But it came back with a 302, not with a 200, and with a location that says go back to getpost/awesome. So that's the same URL that we posted to. We posted to the URL. And if we look underneath the response, we'll find that that's empty, okay? So on the POST request, there is nothing in the response. There is no page, because what we're seeing here is the result of this GET request, okay? So what happens is that the browser sees the 302, sees the location, and immediately turns around and does a GET request. And then that GET request has this page, and then it's going to get a favicon, which is just another GET request. And so this is the GET after the redirect, and we can see the data that's associated with it. And it's got this one actually has a real response, it's a real 200. And then we have the real page, and that renders it. And then it grabs the favicon, just so that it can put a cute little favicon up there. Now, if we hit Refresh, so we sit on this page and we hit the Refresh, then what'll happen is it'll rerun the most recent thing. And the most recent thing that we got was this GET request, which means it does another GET request. Whereas before, it was redoing the POST request, and that's why it was complaining. So you get no message, you get no problem, you get absolutely nothing. So it's actually really quite pretty. So here is the pretty little way of doing it. And the first rule is, at the bottom of a POST method, you should be redirecting. If you're sending a screen back at the bottom of a POST message after the data has been handled, then it's a mistake. So the steps are we go to the page, we do a GET request. There is no message, so we get sort of the page with no message. Then we do a POST request, the POST request comes in. We check the guess. We put the message in the session, and then we redirect, and then it comes back to a second GET, pulls the message out of the session, deletes the message from the session, and then renders it with the message and everything. And it's called flash method, flash message pattern in particular, because we're deleting it after we've shown it to the user. So next we're going to switch to how Django actually has forms.py, and makes it easy to construct forms. So we're not going to be writing a bunch of input tags, or option tags, or select tags. Django makes this a lot easier for us. [MUSIC]