Creating a Chat App With Flask-SocketIO (2023)

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hey everyone in today's video I'm going to show you how to build a simple chat application using flask soccer IO so let me just demonstrate it here I have two windows here they're both connected to the same server for one I'll have my user be Anthony I'll hit join for another the user will be Herbert out here join I'll say hello and we see Herbert hello on this one I see Herbert hello and then if I type in Anthony says hi we see Anthony and then Anthony says hi so each username is associated with a different window because these are separate connections so this is the simple app that I want to show you for flask socket IO and I'm sure this will be a good starting point for any app that you're building that has like these real-time connections and before we get into the app I just want to say that if you need any help with using flash socket IO or socket i o on the JavaScript side you can check out my coaching program at pretty printed.com coaching or you can go to the link in the description below for the coaching and it's basically a service where I help you one-on-one with your project so you can get everything done as quickly as possible without spending too much time like searching the internet for answers when especially for flat stock at i o you're not to find too many because there's just not that much information about it so if you want one-on-one help from me just go to my coaching program and I hope to see you there so now let's get into building the actual app to start this project the first thing I want to show you are the files that I already wrote so first I have a virtual environment set up already it already has flask installed and flask socket i o so we won't have to install anything in this video but of course if you're following along you'll have to install those two things next I have the run.pi file it Imports the create app function from the chat app package and then it just calls it and assigns the return value to app so the app can run next I'll go into chat app and I have Dunder knit so this defines the create app that I just showed you instant cheese flask and it says debug mode to shrew which will be important when it comes to running flash soccer i o in development and I also have a secret key just set to secret I'm registering this blueprint main which is defined in this route stop pi and it simply returns a template called index.html I have this extensions.pi which I'll use in a moment for fast socket IO but at the moment it is empty and then finally I have the index.html which has some CSS in here HTML obviously and I'm going to have JavaScript in here as well so here's what it looks like it's just this simple page I type in a username hit join and then when the app is running I'll see the the chat window and all the messages but for now just shows this and I'll write some JavaScript to switch between the two views and uh that's it so let's get started with the flash soccer IO stuff and since I'm in the index.html the first thing I want to do is bring in the script for soccer IO so I'll just paste it in here and it comes from a CDN so you can get this from the socket i o website and just paste the script tag in here with the link to the latest version just like this and then inside of extensions I want to import a flash soccer so for this I'll just say from flask underscore socket IO import socket IO and then I'll instantiate it so socket IO equals socket IO just like that and the reason why I'm doing this is because in most tutorials that I've seen all the code is in one file it's in like one app.pi file and that's not really realistic for apps that are even slightly complicated so I figured in this tutorial I'll show you how to actually use socket IO flat socket IO in the application Factory pattern that I have here where you have multiple files for your entire project so now that I have this normally what you would do with an extension is you would go to Dunder knit and then you would import from that extensions directory and then do like socketio.nit app and then pass in the app it won't work quite that well because of the events that need to be defined on the socket object so what I'll do is I'll Define a file called events.pi so events.pi this should actually be in the chat app directory so I'll move it and what I'm going to do is I'm going to import the socket IO object from extensions into events so from dots extensions import socket i o so I have that here and in this file I'm going to Define all of the events for my socket and then what I'll do in Dunder init is I'll import from this events so the idea is in extensions like I just have a socket IO object with nothing on it in events I'm going to add all the events onto this object and then in Dunder knit I'm going to import that object that already has events and I'm going to a knit app here so I can say from.events import sockets IO and then just down here somewhere I can say socketio.nit app and then pass in okay so it's pretty familiar issues instead of importing from extensions like you do with almost every other extension you want to first load the events or listeners onto the socket i o object first and then import from the file or package where that's being done so I'm just importing from events.pi okay so let's go back to events and I can just close extensions and under knit I want to work on the simplest possible event that can happen and that's the connection event so to do that here it is similar to defining routes and flask I take the socket i o object and I put a Ampersand before it and I do socket i o dot on so this is kind of like app.route or the name of a blueprint dot route but here at socketio.on and then you name an event so in this case connect so connect is a special event and the other events are ones that you can come up with yourself but connect is the special event here and I can just call this let's say handle connect so all I want to do here is I just want to print client connected just so we can see right so when I run the app and someone connects through the socket connection it will print client connected next what I want to do is I want to actually connect from a client in the JavaScript so I'll go back to my index.html and remember I loaded the Javascript file for socket i o and I can just go down to the bottom and I can start creating a section for the JavaScript of course you can put this in a separate file for JavaScript but for here I'll just put it in the script section so just like on the server side I need some kind of socket IO object so here I'll just make it a constant and I'll call this socket and what I need to do here is I need to connect so you just use the i o function and if you use it by itself like this everything works so I'll just do this and I'll run the app and then later I'll come back and modify this so it works a little better for our purposes but I'll show you this first so before I can run this I need to make sure that socket i o is running properly so if I go to my run.pi I'll be running the app but I won't be running the socket part so I want to run the socket part so to do that I need to import the socket i o object from my chat app package and then what I want to do here is I want to say socket IO dot run app just like that so when I call this run.pi it will run using socket IO and that's because it's setting up like a different type of connection and I see here web transport not available install simple websocket for improved performance you can install different things to actually transport so you know what I'll install something called eventlets you don't necessarily need this there are different versions of it and I'll go more into this one I have the video on deploying this to a server but for now you can use eventlet and let me just called run.pi and it's going to look the same mostly but over here we're going to see like a number and then wsgi so that's how you know the socket stuff is working so now I'll just go to my page and reload and we see here client connected right so it's printing client connected because that's what I have in my events file client connected and the reason why this happens is because in here this i o will connect to the URL that's passed here and if you don't pass in a URL it will connect to the same server that generated this page here so that's why it connects to the same flask app so this isn't what I wanted to do I don't want it to connect automatically because that makes it a little harder to write the following code like after this so what I'll do is I'll pass in some configuration information to this so you pass in an object and the key that I want to add is auto connect and I can set that to false and then save that so now when I refresh the page we don't get a client connected right I still have one client connected I don't have two because there's no longer Auto connecting and if you want to connect after you do it like that you just do socket.connect and now let me refresh again now we see client connected right so we have one here and two here just it's kind of hard to see with all the uh messages but we have the second instance of client connected so this isn't where it's going to be I just want to demonstrate that you can connect manually and the reason why I want to do that is because I want the connection to happen after they put in a username right so like they'll land on this page they'll put in a username click join and then they'll connect to the server through the socket i o connection so let's work on that now so I have this button called join button so I'll just take that ID and what I'll do is I'll put an event listener on click so document git element by ID pass in the ID that I have there and then add event listener click and I'll create the function here and the first thing I want to do is I want to get the username that they selected so I can say let username equal and then documents it should be document git element by ID and then the actual text input so where is that for username so the ID is just username n dot value so this will be assigned the value that the user put into the username input and then I want to use sockets dot connect so now that I have a username I can connect and then what I can say is after the connection has been created I want to send this username over to the server so to do that I can do socket.on just like on the server I have socket on connect I want to do socket on connect here and then I'll pass in the function that I want so an anonymous function and then inside the function I want to call socket.emits and let's call this user join and then I want to pass in the username as the second argument so username so what I'm doing here with emit is I'm sending a new event over to the server and the server can listen to this and it will be able to get the username that the user connected with because it's sending the username to this user join event so over here I can say socket IO dot on user join say handle say handle user join it's going to take in a value it's going to be the username because that's what I'm sending over and I simply want to print user and then this will be F string so user username joined right so f and that should be it so let me go ahead and refresh and now I'll put my name in Anthony I'll hit join go back and we see user Anthony joined right so I'm sending an event from the client over to the server and this happens only when I click on the button so I only connect after the user clicks on the button I get the username and then I send that over so like I said at the beginning of the video I want to hide the username select and the join button and switch the chat view after they join so I can do that inside of this event listener as well so after the connection listener what I can do is I can grab the chat area I believe and display it and then I'll hide the username area so uh let's see I'm calling the username area landing and the chat area chat so in here I can do document git element by ID let's do chat first and I simply want to hide it so I can say Style dot display equals none and then I'll do something similar for the landing and actually I did that backwards so this should be block I want to display this and then for the landing I want to hide it so get element by ID Landing style dot display equals none okay so that will hide the landing page and it will show the chat so let's try that I'll load this again I'll just put a for the username hit join and now it shows the chat window and then the place where I can type in a message okay so now what I want to do is I want to work on this part where I can send a message to the server so as you can probably imagine it's going to be similar to sending like the username over with user join except I'm going to send a message so outside of this event listener I want to do documents git element by ID and then I want to get the input so here it's called message and I want to add an event listener to it and because I don't have a button here I'll just do it based off key up so depending on the key that they select it will do something so I'll pass in the function here and the key that I'm looking for is enter so basically when it hits enter it's going to take all the text for the input and send it over to the server so I can say if event dot key is equal to enter and I should put event in here so if event.key is equal to enter I want to grab the message text so I can say uh just message equals document.getelement by ID and then message so same one and just get the value and then I want to emit this so socket dot emit instead of emitting user join I can emit like new message and then I can pass in the the actual message here so message and then I just want to set the message input to be empty so I can do documents get element by ID message dot value is equal to an empty string to make it go away and then on the server I can handle that pretty easily so I'll go over to events I'll do socket i o on a new message and then handle new message it's going to take in the message and I'll print this for now so print new message so let's give this a shot I'll reload the page oh create username hit join this is the first message and I'll hit enter and insert doesn't work so let's see what happens I'll go to my console I'll hit enter again actually I see it's working it's just not setting the value back to an empty string so let's see get element by ID message value oh I put two equal signs instead of one so that's a minor thing so I'll just try this again we'll do Anthony and then this is the second message enter okay so it goes away it sends over to the server and we see new message this is the second message so what I want to do with this message now is I want to kind of reflect it back to all the clients so I can go to events and instead of just printing what I can do is I can emit so I need to import emit from flash soccer iOS so from flask underscore socket IO import emit and I'm going to send an event called message or how about chat to make it a little more clear chat and I want to send let's call this a dictionary so you can send either like a string or you can send a dictionary which will be an object in JavaScript so for now I'm just going to send a message and later I'm going to send the username but for now I'll just send the message that came in so message and the way to send this to all connected clients is to use broadcast equals true so this will receive a message from one client and then it will broadcast it to all the clients and then if I go to index.html as you can imagine I need another listener and I can just put it down here so I have socket on and then chat and then I'll have a function this function is going to take in an object so I'll call this data here and what I want to do is I just want to append it to the chat area so in the chat area I have this unordered list and I'll append some list items to this so let's say UL I'll say let UL equal document.getelement by ID and what I call this chat messages and then I'll create an Li element so let Li equal document dot creates elements and I want to create a list item element and I want to append so a pin child so the actual text of the LI element I want to create a text node so documents creates text node and the text is going to be the message so data is an object and I can access the message by doing the square brackets and message just like that so I'm appending a text note with the message in it to the list item and then I can append the list item to the unordered list so a pin child and then Li just like that and depending on how many messages I have I'll just fix the Scrolls so I can say UL dot scroll top equals UL dot scroll height and this is just so if I have like 100 messages it will jump to the bottom where like the most recent messages every time a new one comes in so if they scroll to the top it will jump back down to the bottom but you don't necessarily need this for it to work so let's give this a shot now if I go here and I'll just put in a username hit join and I'll just type in hello I typed hello and I see Hello here so that's exactly what I want and let me open up a new one I'll use my last name Herbert so hi there and we see hi there is in this one and it's in this one right here so these two windows are two different connections and they can talk to each other and we see it there so now the last thing I want to do is I want to associate usernames with these messages right because right now it's just I have these two windows and they put in a username but that username information is lost so let's retrieve it let's go back to events and the first place where we get the username is in this handle user join here so the first thing I'll do is I'll create like a global object for users so users equals this and this works well for like a small application in a real application you may want to use something like redis to keep your Global Information but for our purposes in this video we can keep it really simple and just have a dictionary here that's Global and what I want to do is I want to create an entry in this dictionary so user join here I want to create an entry users and I'll use the username so whatever the username is will be the key to this dictionary and the values to this dictionary I want to be their session ID so the session ID is going to be on the requests object from flask so I can say from flask import request and then here I can do requests dot Sid so Sid is the session ID for the connection so each connection has a unique session ID so what I'm doing is I'm associating the username with the session ID and then later I'll be able to pass this username by using the session ID and emitting not only the message but the username so let's save that and before we admit let's create a username variable so username equals let's say none so I'll Loop over all the keys so I can say for user and users if users of user so the user is the key is equal to request dot session ID I want to set the username equal to user so this should have a colon so the reason why I'm doing this here is because this is independent of this so imagine I have like five users connected a new message will come in and in addition to the message text I'm going to have the session that sent the message I want to know the user associated with that session so I have to do this here loop it's kind of ugly because of the dictionary that I'm using but the idea is I'm just looking in the dictionary for the user who has the matching ID and then I'm setting the username to be that and then in here in the emits I can do username username so it sends it to the front end and then I can go over to index.html and in addition to the message I can do like data username and then plus colon and then plus the actual message so let's give this a shot and I'll save this I'll close both and I'll join with Anthony here join hello so now we see Anthony hello I'll join here as Herbert and I'll do hey we see Herbert a and then Herbert hey here I high and high okay so let me just put a space here so it looks better but that's the basic idea and of course you can chat as much as you want hello and we see it's associated with the user automatically because it's looking for the session ID on that user so there's so much you can do in an app like this but I wanted to keep this video somewhat short so other things you can do is you can have like a user system where instead of associating usernames with a session ID you would instead have users in your database and then you can associate multiple connections with one user so like if one user has multiple windows open all of those connections work under the same user another thing you can do is you can save the messages to the database so when you refresh the page you have like a chat history um there are so many different things you can do but like I said I wanted to keep this simple I'll probably make more videos with um flash soccer i o in the future so I'll use some more complicated examples to kind of show you what you can do with it but that's all I wanted to cover in this video so if you have any questions about anything I've done here feel free to leave a comment down below if you like this video please give me a thumbs up and if you have subscribed to my channel already please subscribe so thank you for watching and I will talk to you next time
Info
Channel: Pretty Printed
Views: 21,928
Rating: undefined out of 5
Keywords: flask, socketio, flask-socketio, real time, chat application, chat, python, programming, tutorial, socketio tutorial, flask socketio tutorial
Id: AMp6hlA8xKA
Channel Id: undefined
Length: 24min 31sec (1471 seconds)
Published: Thu Mar 30 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.