Django Channels + Vue.js + Celery + Redis: Real Time Table - CoinMarketCap Clone | WebSockets

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
this project is the logical continuation of the previous project but this time it's the clone of the coin gecko project or coin market cap every 30 seconds django performs and get requests to the api of the coin gecko website save the needed data to the database and then sends the data via opened websocket connection to the front end and we can see dynamically changing table if the price raises it's highlighted with green if it falls it's red i used ujs on the front end the project uses django channels radius silvery and vgs it's very similar to the last video first of all i want to create a basic django project with one app and one template let's install janga now let's create a django project let's say it will be the cmc coin market cup project i'm changing directory okay and then i want to create an app let's say it'll be the coins app i need the manage dot cpy file start app coins also let's apply migrations then on the level of the manage py file i want to create the static folder and the templates folder static templates in the static folder i want to create other styles css and in the templates folder i want to create an index html file index template let's fill it with some content i want to use bootstrap css styles getbootstrap.com css only link i want to paste it here also i wanted to use vue.js viewjs.org get started guide three installation cdn package and i need this script tag somewhere here then i need to add the templates folder and the static folder to janga so i need the settings pi file here in the installed apps i am appending my coins app then the templates last it's theirs last i'm appending with a new path it's the templates folder the name of the templates folder and somewhere at the bottom i want to add the static files last and the same based your variable join path method and the static the name of the static folder and in the index.html templates i want to load the static function and to use my style.css file so i'm using the load tag load static then i'm creating a new tag and then the href attribute will be the call of the static function and i am passing the styles css the name of the styles css file as an argument then i'm going to create a new road a new url pattern and a view to render the index.html template so in the urls py in the root urls py i'm creating a new url pattern it will have the root url address and this pattern will include the urls py file of the coins app then i have to import the include function and to create the urls pi file in the coins app folder here's the same from jenga euros import path the ural patterns last gets a new element a new path it will be again the root url address and the handler of all requests to the root url will be the index function let's import it and let's define it in the views py file the dot here means the current folder so i need the usb y from the coins folder dev index that gets a request object as an argument and it will return the result of the render function and gets the request object as the first argument the name of the template that should be rendered it will be the index html and the context dictionary with some key the text for example and the value let's use it let's use the text key the text variable in our template i need to add the standard bootstrap layout container diff will have the row on def eights columns for example or maybe even six then i want to have it centered and margin from top and five bootstrap units and this cosex dev block will have h3 header and here i want to use the text variable the text key of the context dictionary and in the styles css file i want to color the h3 header to the green and let's test it let's run the server style css not found okay something wrong with my settings py file because static css file is not found so the load filter works well so static files dares of course sorry for that let's try again okay now it's working the next step is to get data from the coin gekka api and render it on the web page let's install the requests library then in the coin gecko website coingecko.com resources resources menu api if you want you can use the coin market cup api but you have to be registered and you have to get the api key and the coin gecko website allows us to use its uh api directly so the coins section and i need the coins market try it out it wants the currency i want to use usd and execute and we will get this huge json object for the first 100 results 100 coins to get on this json object from our django app we have to use this url address let's copy it request url and now let's change the index function let's import the requests library and in the index function body i'm creating the url variable that will be this address after that i want to perform a get request to this url address so the coins variable will be the requests library i'm calling its gets method and i want to get to perform a get request to this url this expression will return a response object i want to have the response body serialized so i'm calling the json method that will return the python dictionary so the coins variable is the python dictionary and then i want to pass the coins variable to the index template let's see the coins variable and i want to use the coins variable in the index html template so let's close the styles and urls here i want to have the margin from bottom at five and let's start the for loop for coin in the coins variable and here i want to paste the coin variable let's test it again and we can see this data that we got from the coin gecko website okay it's working and now i want to create a better html layout for these dates i want to use a table and i want to use bootstrap styles let's delete it so i need the table it will have the table css class and the table over css class it will have the t head tag one table row and maybe three cells in this row with a scope attribute you can find it in the bootstrap documentation i need three cells and i am expanding this formula to this structure i want to have the rank of the coin the name and the price then the tip body and then i have to use in inside the key body tags the for loop and for each element of the coins last for each coin it will use the tr tag then in each row i want to use a td table data tags i need three td tags with a line middle css class dd dot align middle the first one will contain the rank of a coin let's turn back to the api of the coin gekka the rank is market cap rank copy it and paste it here coin dot market cap rank then the middle cell will contain the image the logger of a coin so the src attribute will get this url image image key then the name coin dot's name and the symbol i want to use the small tag with the text muted css class it's it's the bootstrap css class and paddings on x-axis will be two two units and inside this tag i want to use the coin symbol and maybe the same for image i mean i need the class plus that equals to px2 and the price the price will be coin and current price let's test it okay image is too big let's set the width for this image at 15 pixels nice very nice i think that its columns will be better okay i want to move the table to the left side for convenience and that's all for now the next steps are i needed to create a model to save these coins data i need to save it because i want to use the difference between the current price and the price of a coin that i will get in the future and thus i need to save somewhere the state of the object the state of currencies of coins then i need to move the body of the index function view to a ciliary task to execute it periodically and after that i want to use a view framework to render changing data so let's create a model for coins in the coins folder in the modules py file i want to create a new class coin models model that will have the name of the coin the symbol just copy it and rename it to the symbol then the price it should be flawed field default value will be 0 blank 2 then the rank should be [Music] integer field the same default zero blank true and the image it's a url address so it should be url field null 2 and then i want to use the str method that will return converted to the string the name self name of course attribute and i want to define the meter subclass to order this coins ordering attribute and i want to order it by its rank okay i have to create a migration files and then i have to apply them manage dot py make migrations and migrate great the model is ready and i want to use it but i want to do it in a silvery task so well let's install the silvery with all its radius dependencies pep install ancillary radiss as you probably know from my previous videos celery is a task cues management tool a task can be any function you want and a task can be the function that performs a request to an api for example or performs a web scripting or maybe 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 apps now i want to integrate the salary to my django project let's create in the child cmc project a new file on the salary dot py file let's import the oauth model then os environ is a dictionary that contains all system environment variables and i have to get the path to the django's settings py model to do it i'm calling the set default method and its first argument is the key the django settings model in upper case and the set defaults method will return the value of the django settings model key of the environment dictionary if there is no jungle settings model key in the environment dictionary it will create this key and it will assign to it a new value that it will get from the second argument so the second argument is a cmc project it's a path to the settings pwi model so cmc project dot settings so let's import the ciliary class from ciliary import ancillary let's create an instance of the ciliary class it gets the directory that contains the silvery py file in this case it's the cmc project then i want to specify prefix for the sealer configuration code which i will use in the settings py model so to do it i'm calling the config from object method the first argument is a django conf column settings and the name space will be silvery the name space is the prefix that i want to use in the settings py model and then let's call the auto discover tasks method and now let's open again the settings by file and let's define here the silvery broker url variable it will be the url of the redis server the default port is a 6379. how the celery works ciliary provides workers the walker is a function that executes our tasks a task in its turn is a function 2 that we define in our django projects each worker is running in a separate process and janga somehow should pass our tasks that we defined to these silvery 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 janga app it puts the task in a queue and then it starts to pass this task to workers after a worker completes its task it will put the result in the so-called results backend and then we can fetch these results from janga app usually the same broker is used to store the results and the most popular brokers are redis and rabbit mq in this tutorial i'm using redis and so you have to install the radius on your system and thus the silvery broker url variable contains the path to the redis server so i want to start it the default port number with the ready server 6379 that i used here and the last thing i want to do i want to load silvery automatically when jungle starts so i'm opening init dot py file of the cmc project folder and here from dot silvery dots is the current folder this module i am importing the app variable and save it as silvery app variable then they all is a list is a the list of names that will be imported with the and the all variable is used with the expression like from x import all when we use osterix and that's all now let's create a new hillary task let's create it in the coins folder it will be the tasks poi file and here i want to import the requests library and let's define a new function let's name it get coins data for example and let's copy here the body of the index view let's delete the context dictionary and let's delete the import of the requests we can close it tasks and paste it here let's name it to the data then i want to save the data that i got from coin gecko api to my database and i want to do it here in the tasks py file let's import the coin model from dot models import coin and then in the body of the gets coins date function i'm starting a new for loop because i want to iterate through the date list and get needed data and save them to the database so for coin in data and then i need the coin model manager coin model the objects attribute and i want to call it gets or create method get or create that will return an instance of the coin model that was saved in the database already or it'll create a new one and i want to use the symbol of a coin as an identifier so the symbol will be the coin variable this one the element of the data last and its symbol key okay the get oncreate method will return a tuple with two elements the first element is an object an instance of the coin model obg for example and the second element is the created variable it's a boolean value that says whether the object was created or not i got an instance of the coin model in the obg variable and now i want to fill it with the data that i got from the coin gecko api i need not all data i need only rank name symbol image url and the price well object name it's the attribute of the coin model the name that gets the value of the name key of the coin object the element of the data list we get it from the coin geck api the same symbol then the price on the g price then the rank market cup rank and the image called an image and i want to save the object to the database so i'm calling the object save method then i think that i need an additional info about the price whether the price is full or raised or the same so before the current price will be saved into the object variable i want to check whether the values if object price is greater than the coin current price if it's great the state variable will be equal to full well if object price is the same as the coin current price the state will be the same and again oh if object price is less than current price then the state is a raise okay i got the saved object and the additional info about the state of the price and now i want to pack all coins into a list and then i want to send this list to the front end via websocket connection so i need a list in your list coins them as empty list and then i want to append the coins last with the data of each object and the state of the price and we can do it with the modal to direct function that i have to import from jenga forms models import model to indict and here after object is saved i am calling the model to index function and i am passing into it the object variable and it will return a dictionary for example it will be the new data dictionary that i want to update with a new key value pair so i am passing into it a new dictionary with the state key and the state as the value and that's all and now i can append the coins last with the new data dictionary it's done i have created the getcoinsdate function and now i have to say to silvery that it's my task and that it should be executed every 30 seconds let's import from silvery import shared task decorator and use it with the get coins data function if you are an unfamiliar with the decorator concept consider watching of my python decorators video okay the task is ready and now let's define its periodic execution i need again the silvery py model somewhere here i'm going to configure the silvery scheduler the beats so app on bit schedule it's a dictionary and its key is the name of the task let's say it will be get coins data 30 seconds and it's in its turn it's the dictionary too that has the two keys the task it's the path to our to our get coins data function so it's the coins directory the tasks model and the name of the function get coins data and then the period of time the schedule 30 seconds that's it let's test it but to see that the task is working let's add the coin model to the admin panel so coins folder the admin from dot models import coin class then admin site register and i'm passing the coin class into it also i need to create a super user create super user and now let's get to admin dashboard we can see the coins models and so we can see that there is no coins zero coins and now let's start the sealer walker and it's scheduler the bit but maybe it's better to reduce the period of time to for example 10 seconds then on the level of the manage py file i have to call the ciliary command capital a application and then i have to specify the name of the directory that contains the cpy model it's a cmc project then what i want to start i want to start the bit and i want to see what's happening so l logger level will be info and the same command for the worker silvery dash a cmc project worker l info and let's start it beats the worker task coins get succeeded okay refresh the page and we can see saved coins great it's working stop it okay the next step is to install channels integrated to the project and to send messages from our task from the get coins data function to the channels consumer so let's install channels pip install channels and channels dash redis and now i have to append the installed apps lasts with the channels app then i have to modify a bit the definition of the synchronous application that is defined in the ascii dot py model that is located in the cmc project folder so i need from channels routing import protocol type router class and the application will be an instance of the protocol type router class that gets the dictionary and it's http he will be the result of the get onscreen application function and now i have to use this application so in the settings py file i'm copying this visual application variable and change it to ascii application the path should be asgi as well okay let's restart the development server and we can see that they ask asynchronous servers running and now let's define a web socket a router and a handler like we usually do with the core janga apps 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 and i want to create it in the coins app folder coins routing dot py and here as usual from django euros import path ws ural patterns list will get a new element the path it will be ws coins for example and the handler will be coins consumer class i'm calling its as osga method and janga core such handlers are called views as you know but in january channels they're called consumers so let's import it from dot consumers import coins consumer then let's create the consumer's py model and let's define the class here consumer it should be an instance of the async websocket consumer class from channels generic websocket import a sync map socket consumer pass for a while because i want to use our ws url patterns list i need again the ascii.py file and the application dictionary gets a new key websocket that will be an instance of the off middle over stock class that gets the url router instance and it gets our ws url patterns last as an argument so let's import from channels routing url router class and from channels off import oauth middleware stack class then from coins directory from routing model let's import our ws sorry w as ural patterns that's all here let's define the connects method to accept the incoming connection from a websocket and as the coins consumer class is a subclass of the sync websocket consumer class the connect method should be coroutine so async dev connect that gets the instance of the coin's consumer class the self argument and then i want to accept the incoming connection awaits self accept i want to add the incoming connection to a group of channels to do it i am calling the group add method again awaits self channel layer group add and it takes two arguments the first one is the name of the group let's say it will be the coins group and the second one is the channel name self channel name the channel name is assigned to a channel automatically so it's time to configure the channel layers in our settings py model somewhere here i'm creating the channel layers variable it's a dictionary like the databases and as you remember from the previous videos the channel layer is an ordered first in first out data structure it's a queue of messages key of tasks that this data structure receives from its clients from the producers and for every message on the channel in this queue in this data structure django will call the assigned consumer in my case for each message for each task in the channel janga will call the coins consumer class so to use the channel layer i want to use redis as a message broker as i said earlier we can specify here many layers like we can use several databases but the default layer will be enough default in lowercase it's a dictionary too that has the backhand key and the back end will be channels underscore radius dot core radius channel layer and then i have to specify my radius server it's the config key it's a dictionary that has the hosts key and the host key is a last list of ips and the port number 6379 that's it okay let's back to our consumers and now i want to define here the disconnect methods just copy the connect method and gets the closing code as the second argument also i'm calling the group discard method and i don't call the accept method and now i want to send a message to the coins group and i want to do it from the salary task from the getcoinsdata function so let's open the tasks py file and first of all i have to get the default channel layer that we described in the settings pi module and that is used by the coins consumer class i added a group to it so let's define it the channel layer and i'm calling the get channel layer function that i have to import from channels layers import get channel layer the get channel layer function is an asynchronous function that i want to call from the synchronous function from the getcoinsdate function to make it possible i want to use the async to sync function let's import it from asgi ref sync import async to sync and then in the getcoins data outside the for loop i have to call it async to sync as an argument it gets the function as an object that should be converted to a synchronous function and i have to pass into it the groups and method of the channel layer instance channel layer groups and i want to notice that i pass 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 2 but it will be a kind of synchronous version so i have to call it and the groups and method takes two arguments the group name the first one it's the coins group and the second is the message it's a dictionary that has two keys the first is the type the type is the name of the method of the coins consumer class that will handle the message and let's say that it'll be the send new data method send new data and the second key is the text and as the value i am assigning into its the coins last coins this last type and text okay i said that the handler of the message will be send new data function method let's define it in the coins consumer class async dev and it gets the event as of the second argument the event is our message that was sent by the getcoinsdata function let's get the value of its text new data for example event text and now let's send it to all clients in the coins group i'm calling the send methods but i want to send the coins last as the json objects let's import the json model import json json dumps dump stream and that gets the new data list it's done with the server side of the websocket and now i need the clients i want to use view on front end let's close tasks silvery consumer admin routing settings i need the index.html and before the closing body tag i want to add the script tag but as we're using the static folder for static files you can write javascript code in the separate file and then just add it to the index.html file with the static function like we did before and here in the script tag i want to define a view object the view class has the create app method that i want to assign to the create app constant const and inside curly brackets i'm defining the name of the variable the constant create app and i am passing into this expression the view object then let's define an object that will be used by vue.js library let's say that it will be the coins app object and now i want to create an instance of the view from this coins app object i'm calling the create app method and passing into the coins app object and then i want to bind the view object with an html tag i'm calling the mount method that gets the identifier of html tag so i said that i need a tag with the app id so let's wrap my table with the diff with the app id that's all then in the coins app the coins app object must have the data function that will return an object to and this object will have the message key for example message will have the hello world value and let's use this message variable in the templates for example somewhere before the table as usual curly brackets message it's the same idea like we have in context dictionary of django render function so let's refresh the page cannot import as the application model no model named coins routings line 17 sorry a typo again okay and there is no hello world message because the jungle and view use the same paired curly brackets delimiters and to turn off django template language for the table i want to use the verbatim tag somewhere here very bottom ctrl c ctrl v it should be end verb button closing tag and let's again refresh the page the table is disappeared inspect console and we can see that the market cup rank is undefined because it tries to get the market cup of the coin variable that is not defined in the data dictionary so let's delete all these attributes of this case and let's define a coin just just as dummies coin again okay we can see the hello world message and it doesn't like our for loop for coins okay let's delete it okay we can see our hello world message that was defined in the view objects in the data object and also view created one table raw but we have 100 rows that we should get from the websocket from jungle side let's get data first so in the data dictionary let's define the coins key coins that will be now for a while let's delete the message also let's delete the message from here too and then i want to use the created hook it's a function that will be called when the view instance will be created created and here i'm defining a new constant socket that will be an instance of the websocket class new websocket and as an argument it gets the url of the web sockets the same as we defined in the routing py module in the ws url buttons list so i'm using here this characters it's in the tilde button and then ws then dollar character curly brackets and i am pasting into it the window location host this expression will render here just localhost 8000 port number the default location host ws coins trailing slash don't forget the trailing slashes like here it's something like f strain notation in python the next important here i have to save a reference to overview instance to a variable let's underscore this that will be that will be this so then i have to define the on message method like we did before socket on message it's a function that will get an event from the browser after we get the event objects we need to get the json object that was sent by jung and i want to save this coins last from the event object to the coins key of the data object and here we have to use this keyword but the problem is that the message function has its own this that is why i saved the reference to the view object in the variable so underscore this coins and in this time these coins will refer to the coins key of the data dictionary this coins json parse event date that's it with the web sockets now the layout i have to create tr tags for every coin in the coins lists and i need the for loop for it again like we use in django template language so the tr tag gets a new attribute the v4 attributes it's a view directive and the syntax is familiar for us for each coin in the coins list the coins is the key of the data dictionary and it will contain the list of all coins on each iteration of the for loop the coin variable gets an element of the coins list it will be an object but to use the for loops we have to identify each element of the list so the tr attack gets a new attribute the key and the key will be the coin id and as a key i want to use the idea of a coin object i want to remember you that each coin in the coins list is the serialized instance of the coin model and so it has the id attribute and then inside the for loop we can use needed data the coin rank the coin symbol the coin price the rank the symbol price the name of course and and the image to render the url of the coin properly we have to set the source attribute in a different way so i have to set here the column before the src attribute and delete this delimiters let's test it let's restart the bit let's restart the walker unexpected response code 500 it means that something wrong with with our consumer or service side missing one required positional argument code consumers because forgot to disconnect to rename the method when i copy it and paste it here disconnect of course it's a dark side of all copying and pasting actions disconnect again the silvery beat and occur okay we got the results great it's working and the last thing i want to do i want to highlight the price with red if it's false and with green if it reads and so in the styles css files i want to delete this and let's create a new css classes the full will have the color red and the rays will color lime green full rays and the price cell this one will get a new class if the state of the coin will be raised full or the same and i have to specify the conditional class colon class that gets the dictionary as the value the key of the dictionary is the name of the class that will be added when its value will be true so the this td tag gets the raise css class if the coin state equals to raise and the same it will get the full css class if the coin state equals to fall let's increase the time in the tasks in the silvery py model to make the difference in price significant let's test it again let's restart on the beat and the walker beats walker ctrl f5 okay it's working it's working so if you like the video please leave a like and subscribe to the channel thanks for watching you
Info
Channel: Red Eyed Coder Club
Views: 19,208
Rating: undefined out of 5
Keywords: python, django, django channels, django channels tutorial, django real time, django websockets, django websockets tutorial, django websockets example, django channels project, django websockets real time, django celery, django periodic tasks, celery periodic tasks, django channels vue, django channels vue.js, django project, django real time vue, django real time vue.js, celery django, redis django, django channel, redis, websocket django, django redis, django websocket
Id: wos1uhnd3qM
Channel Id: undefined
Length: 69min 13sec (4153 seconds)
Published: Sat Jan 16 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.