Hello, and welcome to another Django for Everybody code walk-through. We're going to do another walk-through of a different part of the chat application. So this time, we're going to actually do some chat. I don't need this now. So this chat is really designed to run simultaneously. So normally, this would be two different logged in users. This chat doesn't really do anything for ticketed for logged in users. So I'm just going to use two Windows logged in as the same user. So the idea is, and we can see this going on right now, if we do a tools developer console, we can just watch. We can watch this, I'll clear it, and you'll see that every four seconds, it's making a request and it's requesting JSON, I got it. Then we can watch in this other Window at the same time. Clear this. Every four seconds, it's going to do an Ajax request, requesting JSON. Now if we watch the network tab, we can see what it's doing. It's requesting JSON. Now the page is not refreshing. What's happening is in the background in JavaScript, it's actually talking to the server. It's doing that every four seconds, and it's doing the same thing in both of them. So this is a polling application. This could be on completely different computers. It's polling to see if any new messages have shown up. So I'm going to say, new message. This is just a traditional form and this is going to submit. So you'll see a post redirect that happens here, hopes to redirect, I'll come back to that. Then that new message already appeared just because the timing was perfect. So I typed it in on this one and it works. So here is the post. It posted that message, parameters, it sent new message, and it sent the CSRF middleware token. Then the post did a redirect back to talk, and then it showed the messages. So this reset, cancel, chat, this is just a standard form. I guess let's just take a look at the page source here. This form is a standard form. It just is submitting it with a post, and it's just standard stuff for the CSRF middleware token, etc. So the hosting of new messages is not the tricky part of this. So let's walk through the simple posting of new messages. Talk/talk goes into my views.py. So this is my talk main. I don't need this one anymore. Let's take a look at the model file. So there is a data model for this, it's a one-to-many, we've got text fields, we got a primary key, everybody can put more fields in so that we do know who they're owned by, so that we know who is allowed. We do have an owner, but we don't have any trashing. So we don't have to delete this, is a really quite simple at this point. So we got the two fields created at and updated up, of course are handled automatically. So do not worry about this bit right here. For my online system, all it's doing is it's throwing away chat messages that are more than 60 minutes old. You could put code in there like this but it really doesn't implement it, it just is something because of samples that's online. Don't worry about that. What it's really doing here is just rendering chat/talk.html. So that's what the GET request is. So that means if we just hit "Enter" here, I'll come here, hit "Enter" here, that's what happens. Then a few seconds later, I get the messages show up. But you should also notice that when I just hit "Enter" and I do a GET request to that page, for a little while I see a spinning GET. So that all happens here in chat/talk.html. But before we leave the view, it's pretty straightforward, when we hit the "Chat" button here, it's going to send a post data and then the name of this form, and inspect element, that's what I wanted. The name of this thing is a name message. So I'm going to say request post message, and I'm going to set the owner field. This is just a message model, and I'm going to store it and I'm going to redirect back to the GET request. So that's how I do cool new message, and that's what happens when I press this button. Now we're going to find out how in this other tab, cool new message shows up two seconds ago. I did nothing in here other than navigate the tab. Now, we want to see how that all works. So let's talk first about the HTML. It comes down here. This is the source as pre-aided, and this is the template that creates the source. It's a pretty straightforward template. We've got some chat main, chat static is a little bit weird. Let's take a look at how that works. That is this line 63, chat static generates this and if I look at my URLs, I'm mapping the static to something that's in a folder. Let's pop up a thing, ls minus l. In static, there is a single file called spinner.gif, and if I take a look at what spinner.gif, let's just open this up. Spinner.gif is just an animated GIF image of this little spinner, also looks like a Walmart logo. If you look at the page that's generated from the view source, and we've been sitting here for minutes now, but if you look at what originally came from the server, you see that there was no need to click there. Let's do it again, view source, come down here on line 62, what came from the server was HTML that put that spinner out. That just is our way, so I've put this spinner here in case the JASON Ajax doesn't work because if it were to blow up, that thing would run there. Now, I've artificially slowed this down and I'll show you how I did that just to let that spinner show for 1001 to 1002, now it's gone. I can make that speed up a lot by changing this chat talk. But just understand that we often fill the areas that we're going to replace with the spinner so that if something goes wrong, we have given our users a clue. So then we're going to build function updateMsg() and it's probably easier to look at it in view source. I did it again, I didn't mean to click on that, there we go, updateMsg(). So $.getJSON takes one parameter slash chat slash messages, which of course is the URL for chat colon messages, which maps to urls.py. Chat colon messages which is TalkMessages.as_view(), we don't need this anymore. This view right here, TalkMessages. We're going to make it in a LoginRequiredMixin, and then we're going to read all the messages by looking at our message model, Message.objects.all ordered by descend and created_at, and give me the first 10. Then what we're going to do is we're actually going to call this naturaltime, naturaltime is a really cool little Django feature that gives us times and it says seven minutes ago, three minutes ago, rather than some big long time that looks like move along dates February 22nd, Wednesday, 2020 or whatever it is. So I can send them messages back, but then I would have to convert these into prettier things. But I want to convert these inside of Django because I've, this wonderful utility. So what I'm going to do is I'm going to loop through the message array that I got back, and I'm going to return, I'm going to make a new array. It's an array of arrays basically and it's a two-thing where I got the text of the message and a pretty version of the time. Then I append that to the array and then I return the array. So I'm returning an array right now. It turns out an array of arrays. It turns out that having the outer thing be an array is actually sort of tacky, but it's really supposed to. If we look at, for example, we go to the network. When we look at this and look at response, we see that it is an array of arrays. So I can click better on it. It's an array. The outer thing in our JSON is an array, and then I've got just a linear list of arrays. There's two items in each array. One is the text, and the other is the time. So this message payload that's coming back, this is that results, and of course, JSON response serializes it. Then we're going to see how we de-serialize it. I think I might be able to open this window. Yes, I can. So I've got this open and look at the raw data. That's what the raw data looks like. If I look at the parsed JSON, it's an array with 0101, and if I look at the headers, of course is application/json. All that work of producing the response is here in TalkMessages where we create a data structure inside a variable, inside a Python, and then we just serialize it and send it out using Django's built-in response. So that shows how we put messages in, that shows how we feed messages out in the format of JSON. Now, let's talk about how we get those messages into the screen. That's this updateMsg(). So updateMsg() is just a function. Will eventually end document.ready we're going to say, "Hey, Ajax, don't cache the messages," so what that's doing is adding this little number that changes. It's really just the time. But sometimes when the browser sees the same URL over and over and over again, it's like, "Oh, I already got a copy of that," and we're like, "No, don't let us." So we're saying, "Don't cache it. Put a little thing on it so the URL is actually changing." It's just this question mark is like a query parameter and it forces the URL to change. Then what we're going to do is we're going to wait two seconds and then call update message. We could call update message right here if we were in a hurry, but I'm going to wait. The setTimeout is vanilla JavaScript that basically says, "Run this code," and it's a string with code in it. But hey, it's JavaScript and code and data are equivalent and wait two seconds, 2,000 milliseconds. This right here, I could say updateMsg right now and then it would start immediately. But that is this setTimeout is why when I press "Refresh", I get to see my cool little spiny thing for a few seconds, then it's too late. Otherwise, I would just call updateMsg. Got it? Now, at some point, this timer will expire, 2,000 seconds will expire, and then it will call updateMsg. Two seconds later, it starts calling this code and so you see it says requesting JSON and then it calls jQuery to ask for some JSON, and it calls chat/messages, parses it all, deserializes it all, and then calls my code with the resulting messages. The resulting messages, all those messages, which is an array of arrays passed in as the variable rowz, and I immediately console log it. Now, if I'm going to go look at the console logging, I can say, "What's coming back? Oh, It's an array." Yeah, it's an array, and in that comes three minutes ago. Come on, I'm not seeing all the rest of it. Maybe it's only showing me. Yeah, it's only showing me the first one but there you go. I'm console logging. I put these console logs in just because I'm so nervous all the time. Did it really worked? Am I really running my code? Because the browser when it blows up is really quite silent. Very, very silent. Let's go back and take a look at the developer network. At some point, I'm gotten called, log it, and what I do is I go up to chat content, which initially it has the spinner on it and then I emptied out, that's JQuery, just emptied out. Then I go through and I loop through all the rows which might be zero, and it is zero, then you're going to see nothing. Then I'm going to grab the rowz_i, which each row has two things in it, and then the message is the sub zero element and the time is the sub one element, and I'm just using jQuery append to throw a little paragraph in with that text. If you were to do an inspect element here, you would see that this is a paragraph. Come back chat content. Let's see if we can catch it. You might catch it emptying it out and then filling it back up. It doesn't look like we're going to catch it but basically, it wipes all this stuff out. There it did, you see what it did? Here it is and now it's going to wipe it out, and then fill it back up with the same thing. You'll see how it does an empty of that whole div and then it fills it back up and so on. We can see it. Here comes, emptied out and then fill it back up and it's got the same stuff. Now, what's happening is it's all happening so quick that we don't see any flicker or anything here, but every four seconds this is being rewritten and rewritten and rewritten. You'll notice that my selection died because it's not the same. It's not the same text anymore. It's not selected because it got deleted. I selected something and it's about to get deleted. Here it goes, deleted, come back, and you'll also notice the 11 minutes change. At the end of this, when it successfully returned, we'll say, "Well, run me again four seconds from now." The setTimeout, once it runs it, it's one time. There's another way in JavaScript to say run this every four seconds, but I actually prefer waiting for it to succeed because it turns out, and I'm not going into it in great detail, but these things can have errors. Then you can put extra code in here to handle errors. But what I'm doing here is I'm only running this if it is successful, and so I'm only running it again, why bother? If it is slow, because this is asynchronous code, it takes a while, in this case a zillionth of a second. It takes a while between the time it starts to request and the time it gets the data back and cause our code. But let's just say that the server was overloaded. It might take two seconds between the start of the request and the call the code, and so this just says that if it two's that will be six seconds everything. Because if it's slow, I'm going to only add four more seconds. I'll wait until it's all done. I'll wait until I get my data, and then I say, "Okay, run me again in four seconds." Now, this ultimately is a very simple polling application which is inefficient, and there is a technology called WebSockets that makes this a whole lot better, but we'll talk about that perhaps some other day. Cheers.