Django+python builds a message push system

Django+channels+websocket completes a real-time push system

foreword

Due to the company's project needs, it is necessary to build a display website and connect two cameras. When the photos of the cameras are transmitted, they will be displayed on the webpage in real time. Therefore, a small demo of the real-time push system is required, because the contact with django is not long ( About two weeks), it can be regarded as learning while doing. There are many real-time chat systems using channels on the Internet, and relatively few real-time push systems.

Ok, let's get to the point. The demo is developed with pycharm+django, and the specific libraries used are: channels, channels_redis. About the steps of project establishment, you can use Baidu yourself, so I won’t go into too much detail. When pycharm established the django project, it has already established a virtual environment for you. You basically don’t need to do many things, just code directly! ! !
(project name for example below (project:mysite, app:myapp)
insert image description here

project configuration

1. First add the relevant library
toolbar File–>Settings–>Project:(mysite)–>Project Interpreter–>±->channels+channel-redis
Special attention, channels-redis version 2.4.2, choose 3.0.1 will Conflict with the local redis server, the reason is unknown.
insert image description here
Add these two libraries into
2. Modify the project settings and
add the app and channels you created together.
insert image description here
Because we use channels_redis, we will modify it together

ASGI_APPLICATION = 'mysite.routing.application'
CHANNEL_LAYERS = {
    
    
    'default': {
    
    
        'BACKEND': 'channels_redis.core.RedisChannelLayer',
        'CONFIG': {
    
    
            "hosts": [('127.0.0.1', 6379)],
        },
    },
}

3. Modify the routing
(you can also skip this step, just to make the project routing classification clearer and easier for later maintenance)
Add app routing Create a urls.py file /myapp/urls.py
in the myapp directory

from django.urls import path
from . import views

urlpatterns = [
    path('', views.index),
]


Then import your app route /mysite/urls.py under the project route

from django.conf.urls import include
from django.urls import path

urlpatterns = [
    path('', include('myapp.urls')),
]

The above step is equivalent to
modifying directly in /mysite/urls.py

from django.urls import path
from . import views

urlpatterns = [
	path('', views.index),
]

4. Add asgi application routing
We have modified ASGI_APPLICATION = 'mysite.routing.application' in settings,
so create a new routing.py in /mysite/

from channels.auth import AuthMiddlewareStack
from channels.routing import ProtocolTypeRouter, URLRouter
import myapp.routing

application = ProtocolTypeRouter({
    
    
    'websocket': AuthMiddlewareStack(
        URLRouter(
            myapp.routing.websocket_urlpatterns
        )
    ),
})

Here's a brief explanation: it lets you dispatch to one of many other ASGI applications based on the value present in the type scope. A protocol will define a fixed type of value that its scope contains, so you can use this to distinguish incoming connection types.
In short, point to different urls according to your needs (your view function is connected)

Then add the routing of the application
ie /myapp/routing.py

from django.urls import path
from . import consumers

websocket_urlpatterns = [
    path('image/', consumers.PushConsumer),
]

5. Create a background push function Create consumers.py /myapp/consumers.py
in the myapp directory

import json
from channels.generic.websocket import AsyncWebsocketConsumer
from asgiref.sync import async_to_sync
from channels.layers import get_channel_layer


# 推送consumer
class PushConsumer(AsyncWebsocketConsumer):
    async def connect(self):
        self.group_name = 'image'
        await self.channel_layer.group_add(
            self.group_name,
            self.channel_name
        )
        await self.accept()

    async def disconnect(self, close_code):
        await self.channel_layer.group_discard(
            self.group_name,
            self.channel_name
        )
        # print(PushConsumer.chats)

    async def push_message(self, event):
        await self.send(text_data=json.dumps({
    
    
            "message": event['message']
        }))

# 构建函数,便于外部调用
def push(username, message):
    channel_layer = get_channel_layer()
    async_to_sync(channel_layer.group_send)(
        username,
        {
    
    
            "type": "push.message",
            "message": message
        }
    )

6. Don't forget our view function view.py

from django.shortcuts import render
from .consumers import push

# Create your views here.
def index(request):
    for i in range(10):
        push('image',i)
    return render(request, 'index.html')

Here is an example of a simple call
for i in range(10): push
('image',i)
pushes 0, 1, 2, 3...9 to all members of the image group

7. Establish our websocket connection on the webpage
and create an index.html page

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8"/>
    <title>接收端</title>
</head>
<body>
    <textarea id="log" cols="100" rows="20"></textarea><br>
    <script>
        const chatSocket = new WebSocket(
            'ws://'
            + window.location.host
                +'/image/'
        );

        chatSocket.onmessage = function(e) {
    
    
            const data = JSON.parse(e.data);
            document.querySelector('#log').value += (data.message + '\n');
        };
        chatSocket.onclose = function(e) {
    
    
            console.error('Chat socket closed unexpectedly');
        };

    </script>
</body>
</html>

This establishes the websocket connection

test

Open the local redis server, how to open it, please download it from Baidu and open it for testing. It
is the following stuff. The
official website download is too slow, so slow that it makes you suffocate. Don't wait stupidly, please find domestic resources by yourself.
insert image description here

If it is a local test, open several web pages locally, the default is 127.0.0.1:8000. The basic effect is that no webpage is opened, and the last webpage is to print the numbers from 0-9.
insert image description here
If the LAN method is used,
modify it in the settings.py file

ALLOWED_HOSTS = [你本地电脑的IP地址]

In this way, another computer in the same LAN can open the webpage for testing, and the effect is the same as that of local testing.

The above is a rookie, welcome to correct me, haha~
If you don’t understand, you can check the official documents: channels official documents
related documents

Guess you like

Origin blog.csdn.net/qq_41750806/article/details/106078181