Django Channels, Celery, Redis: Real Time Broadcasting API response App (Jokes) | Django WebSockets

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
this is the third video about django real time apps and this time it's a bit complicated projects that uses january channels redis and silvery to perform periodic tasks every three seconds the junga app performs a get request to the api to get a random joke about chuck norris and then sends a message via web socket protocol to the front end this is an asynchronous application that can handle requests from several clients i have here two instances of chrome browser and the second instance the bottom one gets the same jokes because it's connected to the group that gets messages from the jungle app and these messages these jokes are broadcasted or were all clients connected to the same group and i assume that you have watched my previous videos about django channels so let's do it first of all i am going to create a very basic django project with one app and one template let's install janga now i want to create a django project let's say it'll be the jokes project then i want to create an app let's say it will be the jokes app python manage dot poi start app jokes and let's apply migrations my grades command and let's start development server okay it's working now on the level of the manage by file i want to create the templates directory and create inside it an index.html file index.html the content i want to use bootstrap styles so the getbootstub.com and i'm copying this css link django doesn't know about the templates folder yet so in the jokes projects i'm opening the settings py file and i am appending the installed apps list with my jokes app and the templates last it's theirs last i want to add a new path join path and the templates name the name of this folder is an argument then i am going to create a new route a new url pattern and a view to render the index.html file so i want to change the root urls py file and here i'm creating a new url pattern and this pattern will use the urls py file of the jokes app i have to use the include function jokes arrows and i have to import the include function then i'm creating the urls py file in the jokes directory and i'm creating a new url pattern the handler of all requests to this url address it's a root url will be an index function for example let's import it from dot views import index dot here means the current folder and this usby file let's define the index function that gets the request object as an argument and it will render index.html file request object as the first argument and index html file this one as the second the context dictionary will have the text key and the text will be let's say hello world in the index function i want to use the text variable bootstrap blocks with the bootstrap classes i want to have it centered i want to have margin from top 5 and i want to use h3 header with jokes id text let's test it f5 i have to restart my development server okay we have done it many times now i'm going to change my index view function to perform a get request to an api that will return a random joke about chuck norris to perform requests to the api i want to use the requests library so let's install it pip install requests okay let's import it i'm defining the url variable http api i chuck norrisdb.com jokes random after that i want to perform a get request to this url response variable will be requests and get url let's copy it and paste it here the response of the api is a json object with this structure it has the value dictionary and the value dictionary has the joke key and the value of the joke key will be the joke i need so to serialize this json object i have to use the json function json method and this expression will return a python dictionary so the joke will be the response i am getting the value of the value key this one and then i need the joke let's use it instead of the hello world i want to use the joke variable let's test it again and we can see this joke it's working and to get the next joke i have to call the index function again by performing requests to the url but i wanted to get a new joke every three or maybe five seconds automatically without performing any actions and to achieve this result i have to use the silvery library let's install it with all its radius dependencies pip install and inside single quotes ancillary and inside square brackets radius silvery is a tasks management tool the task can be any function you want a function that performs requests to an api for example or performs a web scripting or maybe it's does long and complex calculations and so on all tasks are performed asynchronously and thus it doesn't block the main process that runs our jungle app how ancillary works i'll tell a bit later and now i want to integrate the theory to my jungle projects inside jokes project folder i am creating a new silvery dot py model and the content of the silvery py file will be a bit similar to the content of the whiskey and the ascii files i am also need to import the os model then aus environ environ is a dictionary that contains all system environment variables like paths to python your locale etc then it's a dictionary i am calling its set default method the first argument of the set default method is the jungle settings module string and the second one is the path to the settings py model it's a joke's project folder jokes underscore project dots settings as you can probably know the set default method checks whether its first argument django settings model is in the environ dictionary or not if the jungle settings module key is in the environ dictionary it will return its value otherwise it will insert the jungle settings model key and assign to eat a new value which you take from its second argument and then it will return this new value this value then let's import the silvery class from celery import celery and i have to create an instance of this hillary class silvery and as an argument it gets the directory that contains the silver apy model it's the jokes project directory jokes project then i want to specify a prefix for the silvery reconfiguration code which i will use in the settings py model to do it i am calling the config from objects methods app config from objects and it gets as the first argument janga conf colon settings the name of the settings py model and the second argument is the name space the prefix silvery and then let's call its author discover tasks method okay now let's open the settings py model and somewhere maybe here let's define a new variable it will be the silvery rocker url that will be a path to the radius server local and the default radius server port number is 63.79 by the way let's start it you have to install the radius the port number of the radius silver okay how celery works silvery provides workers the worker is a function that executes our tasks a task is a function that we define in our jungle project each walker is ryan in a separate process and the jungle somehow should pass our tasks that we defined to these workers and usually brokers are used to do it a broker is a task queue that stores our tasks its data structure after the broker gets a task from a jungle app it puts the task in a queue and then it starts to pass these tasks to workers after a worker completes its task it will put the result in a so-called results backend and then we can fetch these results from django app usually the same broker is used to store the results and the most popular brokers are radius and rabbit mq in this tutorial i'm using redis so you have to install the radius on your system and that is why the silvery broker url is a path in the url of the radius server and the last thing i want to do i want to lower the silvery automatically when the jungle starts so i need the init dot py file that is located in the jokes project folder so and from dot silvery model dot the current folder and the silvery is this file i am import the app variable and save it to this hillary app variable let's define the all variable it's the last of names that will be imported with the expression like from x imports all with the using of osterix and that's all now let's create a new silvery task in the jokes directory i am creating a new python module on the tasks py file and let's define here a new function let's say it will be the get joke function let's import the requests library and then i want to move this code from the index view to my get joke function let's delete the context dictionary we can close it and here let's print the joke and let's return the joke okay i have created the get joke function and now i have to say to hillary that it's my task and this get joke function this task should be executed every three seconds so let's import from silvery import shared task decorator shared task if you are unfamiliar with the decorator concept consider watching my python decorators video ok the task is ready and now let's define its periodic execution i need the silvery py model again and here i'm going to configure the silvery scheduler the bits so the app variable conf beat shadow it's a dictionary that gets a new value this dictionary will have one key the name of the task that i want to use let's say it'll be they get a joke three seconds and the value of this key is a dictionary too and this dictionary has two keys the task it's the path to our get joke function so they get a joke function is let's close it let's close euros so the get joke function is located in the jokes folder in the tasks model jokes tasks and yet joke it's a path and the second key is the shadow the period three seconds and that's all let's test it so you have to have the ready server started then i need to start the beat the hillary scheduler and i need to start the silvery poker so on the level of the manage py file [Music] jokes project from here i'm starting the silvery command dash capital a application and then i'm specifying the folder that contains the silvery py file it's the jokes project folder jokes project what i want to start i want to start the beat the scheduler and then to see what will happen i want to use the log logger level info and the same way i'm starting a worker the a jokes project walker logger level info let's start the beat okay and let's start at the walker and we can see that we got these jokes it works the next step is to install channels integrated to the project and to send messages from our task from the get jokes function to the channels consumer so let's stop it and the bit and let's install the channels pip install channels okay now in the settings pwi file let's append the installed apps last with the channels app comma and then i have to modify a bit a definition of the synchronous application that's defined in the ascii dot py file the application variable will be an instance of the protocol type router that i have to to import from channels routine import protocol type router class and it's gets a dictionary as the value http key gets uh the result of the get asgard application function as the value then in the settings dot cpy file i have to use on the ask application just copy this string and change it to asgard application and the ascii model here okay we can restart development server we can see that the asgard server is running now let's define a web socket a router and a handler like we usually do with the core genre apps so let's start with the router we can define it in any file we want but the preferred way is to create a special routing py file that i want to create in the jokes folder routing py and the idea of this file is absolutely the same like of core urls py files i need the path function on jungle heroes import path and let's define ws websocket url patterns path the url will be ws and jokes for example and the handler of all requests to this url will be for example the jokes consumer class and i am calling it as asgay method let's import it i will define it in the consumers model i have no consumers py model so let's create it and here i have to import the async websocket consumer class from channels generic websocket import async websocket consumer and let's define the joke's consumer class it'll be a subclass of the sync web socket consumer pass for a while because i have to use the wsurl patterns list so i need again the ascii dot py file and the dictionary gets a new key the web socket and the value of this key will be an instance of the both where stock class that gets as an argument an instance of the url router class and in its turn the url router gets our ws url patterns list so let's import them all from channels off import both middleware stack class then from routing let's import the url router class and from jokes folder from routing module let's import our ws url patterns last that's it first of all django channels checks the type of the connection protocol type router it checks the protocol type whether it is an http connection or a websocket connection because the websocket is a different protocol if the connection is the websocket connection it will be given to the oauth middleware stack class to identify a user like janga does with its own oauth model after that the connection will be given to the url router class that pass it to the consumer that was defined in the ws url patterns list so let's back to our jokes consumer class we can close asgay p by the routing the silvery jokes consumer let's define the connect method to accept the incoming connection from a websocket as the joke's consumer class is a subclass of the async websocket consumer class the connect method should be a core routine so i have to use the async syntax async def connects in the gets of the self as an argument and then i'm calling the synchronous function self accept method to accept the incoming connection the next point here i can and i want to add the incoming connection to a group of channels to do it i'm calling the group add method that takes two arguments so before they accept method i have to call the channel layers group add method that takes two arguments the first argument is the name of the group let's say it'll be the jokes group it's something like a channel on youtube or a group on facebook we subscribing to this channel to get its updates it's news and the group in jungle channels has the same idea the same goal so the jokes group and then this second argument is the channel name channel name channel name is assigned to a channel automatically and i think that it's time to configure the channel layers as you remember from the last video the channel layer is an ordered first in first out data structure it's a queue of messages that this data structure receives from its clients from the producers and for every message on the channel and this queue in this data structure django will call the assigned consumer in my case for each message in the channel django will call the joke's consumer class so to use the channel layer i want to use redis as a message broker as i said earlier so i have to install channels redis app pip install channels redis then in the settings dot py file i have to define the channel layers variable channel layers the channel layers is the dictionary and we can specify here many layers like we can use several databases but the default layer will be enough default it's a dictionary too the backend key the value channels underscore radius core radius channel layer then the config it's a dictionary and the config will have the hosts key it's the last of ips so i will use a localhost ip 700.1 and the port number is the default port number of the redis server 6379 that's it let's back again to our jokes consumer class then i want to define the disconnect method that will be disconnect the client from the group and the code is almost the same just copy it here but instead of the group ad i am calling the group discard method now i want to send a message to the jokes group what i want to do it outside of the jokes consumer class i want to do it from my celery task from the get joke function from here first of all i have to get the default channel layer that we described in the settings py file so to get it let's create the channel layer variable and it will be the result of the get channel layer function that i have to import from channels layers input get channel layer function the get channel layer function is an asynchronous function that i want to call from the synchronous function get joke to make it possible i want to use the async to sync function let's import it too from osgi ref model sync import async to sync let's remove this and then let's call async to sync function and as an argument it gets the function the function as an object and that should be converted to a synchronous function i have to pass into it the group stands method so the channel layer variable and i am passing its group send method i want to notice that i passed the method as an object i don't call it and the async to sync function will return the group send function as an object too but a kind of it's synchronous version that i have to call i put here brackets and the groupsend method takes two arguments the group name it'll be the jokes group and the message the second argument is the message it's a dictionary that has two keys the first one is the type the type is the name of the method of the joke's consumer class that will handle the message let's name it send jokes method i will define it a bit later and the second key is the text the text of the message and i want to use the joke variable this one that's it i said here that the handler of this message will be the send jokes method let's define it async def self and it gets the event and the event in this case is our message that was sent by the get joke function let's get its value it's text key text message variable gets event and it's text and the text message will get the joke and then i want to call the send method that gets the text message variable as an argument okay and the last thing i have to do is to create the front-end part of the website so let's open the index.html file and let's add the script tag here and i'm creating an instance i want to reload the index.html file something wrong with the highlighting so circuit a new instance of the websocket clause and websocket gets the url pattern as an argument localhost 8000 ws in jokes as we have defined in the routing py file vs jokes then i have to define the on message method it's a function that gets an event from the browser i want to get the joke event data and the data variable the data attribute is our message that we'll get from the sender jokes method it's not a json object here it's just a plain text and then i want to get the h3 header and a change its text document query selector and jokes in our text and that gets a new value the joke that's it let's test it i want to restart the beat and i want to restart the broker okay let's make a request it's working let's create a new client okay it's working if you like the video please leave a like and subscribe to the channel thanks for watching
Info
Channel: Red Eyed Coder Club
Views: 8,111
Rating: undefined out of 5
Keywords: python, django, django channels, django channels tutorial, django real time, django websockets, django tutorial, django websockets tutorial, django websockets example, django real time application, websockets app, django real-time, django channels project, django websockets real time, django celery, celery redis, django periodic tasks, celery periodic tasks, celery with redis, redis with celery, django websocket, celery django, django channel, redis django, websocket django
Id: AZNp1CfOjtE
Channel Id: undefined
Length: 40min 52sec (2452 seconds)
Published: Fri Jan 08 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.