Intro to Django Channels

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
okay so if someone has their hand raised okay good to know so most people aren't yeah mostly you're not familiar with with django well i'm going to be diving into uh addition addition third-party django library called django channels um so this allows uh you to take django which uh in its core um just as http and um synchronous web pages and you can add web sockets which is a great protocol for writing data back and forth from the server and then a couple other features you can build really interactive applications and so in this talk we're going to be walking through how to build a basic uh chat application so you'll be able to send a message and then everyone else on the web on the connected will be able we'll receive it so we'll walk through the basics um so yeah we're going to build a real time chat application it's going to be django plus channels and then just a little bit of javascript um and then yeah channels at its core takes django and allows us to create an event-driven architecture instead of a resource-driven architecture so yeah channels provides two major features to django uh long living connections like websockets as opposed to http connections which don't which only live for as long as the request response and then an event breaker called the channels layer and that's how you communicate in between people is through an event program so this is what django uh looks just on its own nice and simple that's one of the big advantages of django is you have requests to come in and then there's the middleware stack turns it into just a function call um and then you that's a view function and then you return a response and there are class based views but that's also really just a function i prefer to do all my uses functions now django with channels is quite a bit more complicated but one of the advantages of channels is that it preserves that those view functions and they work exactly the same way you don't have to worry about these other layers if you just uh want to add channels to your existing django application so you can progressively add it on you don't have if you're just starting with django which a lot of people here might experiment with it you can always add channels to do cool stuff later like adding real-time data to your uh to your website in some small way so let's a concept that's good to know about is scope um and so that's what i was talking about before the lifetime of a connection so for http the scope is just the request response cycle so there's nothing saved in between that's why http is a stateless protocol uh websockets uh the life of the connection is just until either the client or the server closes the connection and so within that time span you can either side can write back and forth and the connection does have state so an http request scope is just simple client request response profit and then websocket as you can see is a bit more complicated that's why it's preferable to use an http um in in a situation where you're just asking for one thing you don't want to make it more complicated than it needs to be so i'll go ahead and switch now um so i'm going to go and just open up a demo i've just got digital studio code set up so if you want to follow along that's fine but as dan said this is going to be recorded so it might be easier to follow along later um so just a few things first as always is this big enough for everyone anyone raise their hand if they want me to like increase the fluent size i think it looks good paul okay great um so i'm going to create a virtual environment um so that way we just keep all our dependencies separate um i don't really need to do this but i i always do this um and then we're going to enter that virtual environment and then so we've got a fresh um package installed so we're going to have to install django and we're going to install channels and that's all we're going to need for now so that'll just take a second and there we go uh so now we've got our virtual environment uh we want to uh start a project new django project so django admin start project just call it my site oh i think i said probably gonna reopen this actually nope hmm that's way weird let me just uh try that again okay yeah it didn't work before for some reason that's odd um okay now we can start and go admin start project my site and we've got all our basic setup uh so we're going to open up settings.pi uh we're not going to worry about setting up anything else except channels uh so we need to uh run and set up an asgi application so uh this is wsgi stands for web server gateway interface asgi stands for asynchronous server gateway interface this is uh on the like the underline um django this is how it connects to like a web server we need to have an asynchronous web server so this is just a little boilerplate not to really be worried about you're unlikely to ever change this so just go to my site routing application and then we need to also add to our installed apps this is always an easy step to forget add channels and then go and open uh create a new module called routing.pi so this will take care of routing all our requests for application um so from channels dot routing import protocol type router and then we need to find application equals protocol type router and then we're going to put some more stuff here but let's just pause and actually run uh the server now so python manage.pi run server oops i gotta change directory into my site and then and then run the server there we go and right here as you can see it's an ascii channels application so under the hood things are running a little bit differently than they would be normally for a python application and i should add i forgot to begin in this presentation the goal with django with channels is to introduce some of these features um asynchronous web sockets uh that will eventually be added into the django main applica framework uh because the idea with django is that it's the batteries include included framework it comes with templating and the django orm so that's what i really love about django but it's still kind of experimental right now um so yeah we've got things running i'm just going to quickly before i forget python managed up high migrate just so we have our basic user model set up because we're going to be using that a little bit later so now like i said at the beginning channels does not actually interfere with writing uh regular django views so we're gonna just create a basic home page for our site so this is uh if you're familiar with django this is uh just how you set up a home so this is setting up the url um getting ahead of myself actually we haven't actually created an application i got to create an application so python manage the pi start app everything in django is organized into an application um if i manage to i start out chat we're just going to need one application for this and before i forget add chat to our installed apps in settings and now we can start setting up our url so we'll just have empty url go to the chat views dot home so that'll be our home view it's not going to just import that from chat dot chat import views as chat views uh so we're kind of going backwards here this hasn't been created yet we'll just jump into chat views dot pi and we'll define home and if i ever if i make any mistakes anyone is free to point them out because i often do make typos and then request so as i was saying before every view is just a function in django and we're going to make this a simple one it's just going to return a plain html page return render request and then chat slash index.html and now we've just got one step left that was yeah we're going to just have to create this index.html so that always lives in the same place in the templates file and then the name of the application so chat and then index.html now we're going to create a basic html5 page just using a nice snippet there this is going to be our chat room and we're not going to use this until later but i'm going to go and to find out what everything looks like we're going to have a text area this is where the chat messages are going to live let me take advantage of that snippet um so we don't need to have a name we do need to have an id since we're going to be doing a little javascript later chat message input i mean sorry chat log that's what this one is um let's change it make it a little wider a little taller and we'll add a break and then we need a place to actually put the text in for the chat so input it's going to be text it's going to have an id of chat message input type equals text oh wait i already did that size equals 100 just to match the chat log right above it do another break and then we just need a button to press to actually send our messages so that type will be button id will be chat message submit and value will be sent all right so now uh we can go back um to the console and python manage that pi run server we should be able to see all this all right great so we'll just grab a tab in here and uh-huh did i make it i made too many rows did i do whatever i do 300 rows oh 200. i just want 20. there we go that looks good so this is where our messages are gonna go we're gonna click send and they're gonna appear up here so now we've done the basic uh kind of django uh setup we're going to get into some of the more juicy channel stuff so first we need to go back to our writing to pi and actually set some stuff up here so a little bit about this this application this router will actually handle everything that comes in to django so that passes through the server but by default it will just redirect anything that's http to our urls.pi but now we're going to set up routing for web incoming websocket requests but first before i do that does anyone have any any questions dan no questions right now i guess reminder everyone in the bottom left there's a area to ask your questions all right cool so let's see what we're going to do is um before we get into making a chat room i'm just going to set it up so that there's a websocket connection and you'll just get an echo of anything you send um so that's just a simple thing we can do so we're going to import a few more things we're going to import a url um where am i at here url router actually i'm not sure if that's yeah i think it's that and we're also going to import from channels import the off middle where stack this will allow us to actually use authentication in our websockets um i don't think we're i'm not sure we're going to get to that today just to let you know that in websockets you can actually use the user model and actually call to the database and stuff like that so now we're going to set up the url oh wait first we have to define uh since this is this protocol type router is a dictionary we're going to specify that all websocket traffic websocket being the key we'll be going to off middleware stack so that's going to wrap around any request that comes in so we can use authentication and then urlrouter chat.routing.websocket url patterns so we haven't defined this yet so yeah that's going to throw an error down there um so we're going to go into chat and we're going to find a routing.pi so from django.urls import path and then from from this directory import consumers and we're going to go define that in just a minute uh we're going from the top down here and then we just have to define those websocket url patterns just as the same way you would normally divide up your urls you'd split them up into each app would contain its own urls and now we're going to pick a path so i always like to start websocket paths with ws and then slash chat and then we need to have a consumer um for this chat so we're gonna do consumers.chat consumer and now we're going to define consumers dot pi so from channels dot generic dot web socket import web socket consumer this is our base class we're going to use it does a lot of work for us and we're also going to need json oops import json and we're going to find our chat consumer so a view function can be a function because there's just one thing that happens there's a request with the websocket there are three things that can be triggered by the um by the user there's the connect there's the receive and then there's the disconnect so that's why this has to be a class so first we're going to define connect um and all we need to do for connect is just self.accept this is just a little bit of boilerplate we have here um and then we do need to find receive so what is going to happen when the user sends us a little bit of text data because that's what you uh essentially write back and forth over the uh over the websocket so this text data is going to be uh json um just uh formatting for objects so we're just going to go and interpret that we're going to deserialize that so we're going to use json and then we're going to load s load string this text data so now it's a dictionary like object we can manipulate [Music] and i haven't mentioned this but we're going to the way we're going to communicate back and forth is a json object that's going to have one field which is just going to be message and then it's going to contain a value of whatever the message is so we're going to for this uh echo um we're going to just change it a little bit so we're go ahead and text data json we'll get that single message key and we're gonna add echo that way we know it came back from the server and then next we're going to send this back to the user so we also need to send it as just as a string so we're going to need to use json.dump s so take this dictionary next data json turn into string and we'll just send it right back so many questions deserializing so uh serializing is taking um a object in our case just a python object uh like a dictionary and turning it into a string so in a serial format that anything can read and then deserializing is taking a string and then turning it into an object we can actually use in the code and so json is just the json being short for javascript object notation is just a really easy commonly used format for the web okay thanks yeah no problem so now the next thing we're going to do is one last step go into our html page and define how we're going to actually communicate with the websocket from the front part now so i'll go ahead and create a script uh so first things first we need to actually connect to our websocket so we'll just go ahead and and all of this is just vanilla javascript so you can just don't need to import anything you don't need to use npm uh you can literally just create the script tag it'll work in any browser pretty much uh although i can't speak to internet explorer [Music] so we're gonna create a chat socket bar and that's going to be a new websocket which is part of um i'm not sure which version of javascript it is i don't really know too much about javascript i mostly copied this from the channels documentation because i'm not a front end developer um so we just need to put in a path to connect to so just go ahead and w do ws just was slash last just like since the http we're defining our protocol here and then we want the host so we can do window location post this will just ask javascript hey what website are we connected to for this page so that's a nice thing so if we decide to deploy this later to something we don't have to worry we don't have to manually set this to a string called localhost and then we just do the path just like we defined in our routing ws chat just go ahead and type that out ws ch chat so this handle is connecting to our websocket and that opens it up [Music] and now we're going to handle when we receive a message so let's the server sends the client a message so chats this check socket variable has an on message attribute it's going to be equal to a function and so i apologize for doing some javascript in the uh python meetup but it's kind of if you're going to be in the web it's kind of unavoidable [Music] var data equals json.parse e.data so this is um deserializing now actually sometimes i get a package deserializing we're taking a e dot data which is just a byte array turning data into um a javascript object we're going to get the message out of that object so i guess the nice thing about javascript is it does look a lot like python sometimes it's they do have some simulators and then we're going to do take the document query selector so this is how we manipulate our html up here we're going to take our chat log oops and we're going to add uh the value of that we're going to add our message so message and just add a new line at the end yep that's good so that's how we receive um now we're just gonna uh just for convenience sake of debugging uh the on close attribute we're also gonna define um there's nothing much you really can do if the socket closes so we'll just do a console dot error um socket closed just so we know what happened um and the same thing here actually we're going to do console.log e.data just so we can if there is some kind of problem we can check the log see if what's going on and now lastly how do we send over the chat socket so here we're going to start with the document query selector again and now we can use an event that happens um on our chat message oops chat message submit so when any anyone ever this button as your little call anyone clicks this triggers the on click and this is also equal to a function so we need to get uh so just a bit of javascript weirdness first we get up um i'm actually not even sure what this object is this contains uh more than just the information but we can get the actual message um at such value there we go so this is just the plain text of our message but we need to put it in a javascript object in order to send it back to the server so we'll just go and pick our chat socket object and then it has a handy send function and then we just use json and stringify i guess that's a more intuitive word than um serialized stringify but they're they're actually the same thing um and then this is just contained it'll just have one attribute with one value message and now uh it should be good and actually added measure we'll take the message input dom dot value again this is our um chat message input we're just going to set this to an empty string so whenever you create uh send a message it'll just clear out that message box okay so that is all we need to do to have this basic echo consumer so let's go ahead and it seems to be stuck here so i'll go and restart it there's probably some mistakes stuck in there interesting chat is not defined i probably forgot to import that ah yes i did from uh see we want to import chat.rowdy that's right there we go so now we should be able to connect to our site and we'll actually be working with a websocket so go to our localhost test interesting that's i figured there'd be something there always is still in connecting socket closed okay so something wrong yeah it's interesting what what have we here no round found ws chat let's go to our routing let me check um is there supposed to be a slash before that ws huh there's not supposed to be oh did i forget yes the slash after chat i don't think i actually need to restart the server but just force a habit let's open up and so no disconnect hit send json is not defined ah yes i forgot json and all caps for javascript there we go did i forget all right save that okay yeah we're connected there we go and it echoes so we've got something working now uh very good uh any questions good no questions right now okay yeah ask questions in chat everyone okay so we've been going for about 40 minutes um let's see just a quick demonstration about how this works um since we're really right now treating this like http we're only sending one response um we can do more with this since this object persists it stays here as long as the socket is open we can write data whenever we want so we i can just import time uh and then just uh while true just do an infinite loop and we'll just send it back forever um so we'll just do time.sleep for one second so if i go back to the browser reconnect test oops as you can see and this is the json object it looks just like a dictionary in python but we could open another connection and that will also work so these are both running in python but they are running concurrently however they have no way to communicate between uh one another so that's where the channels layer comes into play so that's not a huge change we actually don't need to change the javascript anymore we're just going to change things on the server let me just get my bearings again so the only thing first thing we need to do is go into settings we just need to make a quick change in settings and then change our consumer so we need to add another thing in settings which is the uh channels layer so the channels layer uh takes care of uh it can receive events um from any anything running so including a consumer a view could send an event to the channels layer and then anyone listening on that group and anyone meaning a consumer actually we'll then receive can receive a message uh and then send it out so you could have one person published event and it could go to everyone else so in this case we want when someone sends a message um in our chat room anyone else with that page open and connected to the socket will receive it so in settings we'll just specify the channels layer as another attribute channel layer channel layers actually you can have multiple i'm not going to get into that the default layer and the back end for it will be what's called the channels layers in memory channel layer um and i'll get into what this means right at the end of the talk i think we'll have enough time to cover that so now uh reloading think actually the fact that the socket never closed it could cause some problems on the server but yeah this is running just fine now we have access to the channels layer from anywhere in uh our site so let's go ahead and we're gonna just get rid of this actually first things first what as soon as we connect we want to be able to receive messages from other people so we need to connect uh to the channel layer unfortunately you see we do have to dive a little i do have to acknowledge here that the channel layer is asynchronous i'm just curious uh who's written any asynchronous python anyone want to raise their hand in chat async await okay so some things have to be able to run asynchronously and in uh python and async function uh synchronous function is kind of like oil and water they just won't mix together but there is a handy little utility um we can import so from asgi ref.sync and i'm pretty sure not sure which version of python this might be and it's like 3.7 or 3.8 um we can import the async to sync function so we'll just need to need to use this to access the channels layer so we need to use async to sync right here and then our website can consumer has a function channel layer group add so this will take this consumer and that this function has this async to sync is just to basically take this this is a function and transform it into a synchronous function that's all it's doing so this is we're actually making taking arguments for this group ad so we're adding this consumer to this group chat so anytime anyone sends information to the chat group this consumer will receive it we also need to just i get the identity of this consumer channel name there we go and now when we receive we don't want to just send it back to the user we want to send it to the channel layer so when we receive we also again need to use async to sync self dot channel layer dot group send and we send it to the chat group and then we send in a dictionary which has to have at least one key which is type and type is what will execute on any consumer that receives it so that will be chat message so chat message is a function that we'll have to define in just a second and then we're going to put in our message um which is going to be the text data so this message is actually again this text data is our json as um as a string so we're just going to pass that through so that's all we're going to do on the receive we're not going to send anything now we need to define this chat message so define chat message and so this string is actually referring to a function but if this function doesn't exist there's not going to be any error or anything nothing will happen if this function isn't here so chat message receives an event so we'll just get the message from the event the event is just the dictionary and then we're here we're going to do self.send so this is sending it back to the user across the websocket text data equals message so now we're not actually bothering with the json at all because we're just sending the string straight through back to the user so actually we can get rid of this import json here um and then one last thing um we technically don't need to do but it's a good idea we're just going to define uh disconnect close code so this is just a function that gets called as soon as the chat stop disconnects this will stop errors from happening um we want to all we want to do on disconnect is to leave uh this group so we're no we don't want to be subscribed to it anymore say sync to sync self.channel layer dot group discard is that right yeah that's right so we're discarding ourselves from the chat group and putting our channel name in here okay i think uh that should be all good this should just work now i'm sure there's a mistake somewhere in there but we'll just open back up again do inspect so we can see the console and test and it seems to work so we'll just open up another tab just to make sure um test as you can see it popped back up over here now this doesn't actually have as you can see the first message these are out of sync for that um we would need to actually use um a model um so get getting back into regular django uh single model and then save it to the database and repopulate it but we're not gonna do that today since uh we are running over the normal time so again just to reiterate what happens as soon as i hit this button javascript will register the event it clears the box it sends this over a websocket connection that's open to django django has a websocket consumer which will take that message send it to the channels layer which will distribute it to all the other consumers which only happens to be this but actually it does send it back to itself since this consumer right here is also subscribed but it'll also send it to this consumer where um it'll go to that function and it'll send it to the user where again javascript will get an event and then it'll render it to this text box all right so any questions i'll ask a question well everyone's typing in their questions um so is that async to sync function needed because django right now doesn't um support a synchronous functions so you're converting it between like channels and what django can support is that right um not quite because we could uh use the async websocket consumer instead um and then all of these functions would be async but i wasn't doing this for that for this tutorial the problem is uh just actually more underlying in python you can't call an asynchronous function from a synchronous function so if we said define or async define example down here um that does nothing we couldn't we couldn't call it from anything else so if we wanted to call it from right here we wanted to call self.example um just doing this off the top of my head i'm pretty sure this wouldn't work so if we go back here all right i'd have to add cell maybe this would work okay maybe i misunderstood that um yeah it's because django doesn't uh yeah django it does not support uh async right now um i thought that would demonstrate but actually i just confused myself a little bit more that's why i was avoiding async because it is kind of a confusing topic um but yeah there's when it comes to web development there's uh yeah no no avoiding uh async these days i don't think i don't think that quite as answered your question but yeah that did thanks probably in the future maybe sockets wouldn't even be needed because django itself would be async right or i think that's what you said in the beginning well yeah sockets will still be needed but channels won't be needed necessarily yep yeah that's what i meant sorry thanks yep and and yeah you could take django views um and make them async so uh someday you'll be able to do like this and have async define django music and asynchronous um and the big advantage of that is uh with async if you do it correctly um you can have a lot more efficiency a lot more throughput any other questions else have any questions okay thanks paul for yeah i was just going to mention one more thing um this channels layer here so this is the in-memory channels layer um which is really helpful for development but not so much for production because um django is not very efficient at this uh whole dispatching of these messages um so you actually want to use a separate um broker so that's where you actually would use like redis is uh you'd have a separate application and that way you could have for instance in production multiple instances of django running on different uh virtual machines and they could communicate through one uh central application so you could actually have uh scalability that way i just wanted to mention that what are the files present on the left um i know some of them like i can't hear you very well could you put your question in chat so trent was asking what do some of the files represent on the left oh yeah i guess if you're beginning to django then um let's see so we talked about views so that's sort of the entry point um tests that's for testing routing that handles taking in incoming requests for in just in this case web sockets but we could support other protocols um and then sending them to our consumers urls uh no actually i guess you don't have urls right here um apps and admin are kind of actually not even 100 sure how i would describe these um just adding a little bit more information there models is and that's when you actually get into saving data so important thing to note with this application nothing here is ever saved permanently um which is kind of the uh missing squashing over probably what the best feature of django is is the django orm um highly recommend if you just starting on django that's a really great place to start i literally like to use django and if i was just doing something that i need a database for because i understand it so well um and it's so straightforward um and then um this is our application we can have many of these and then there's my site which is uh just the main package which has like our settings and a bunch of just higher level information about our website so you have one of these and then multiple chat um this rate hey paul at least for me i lost your audio me too is there maybe this probably is a good time to end the you know yeah we can okay yeah that's i was just uh i don't know what the last thing you heard was um oh we just lost you like maybe 10 or 15 seconds ago so okay well yeah um that's just one cool thing you can do with django um probably wouldn't be the f if you're just looking with the not the first thing but yeah eventually you can add real time stuff using django channels great thanks so much paul that's really good you
Info
Channel: Michigan Python
Views: 1,961
Rating: undefined out of 5
Keywords:
Id: xp0JKB-lp6o
Channel Id: undefined
Length: 48min 30sec (2910 seconds)
Published: Thu Jun 04 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.