Create a websocket that listens for forcing refreshing an Angular app
To create a WebSocket-based solution in Django and Angular that refreshes all frontend pages when a button in a certain admin dashboard is pressed, we can follow these steps:
Django doesn’t support WebSockets natively, so you need to install Django Channels:
pip install channels
pip install channels-redis
Update your settings.py
to include Channels:
# settings.py
INSTALLED_APPS = [
# Other Django apps...
'channels',
]
ASGI_APPLICATION = 'your_project_name.asgi.application'
# Channels configuration
CHANNEL_LAYERS = {
'default': {
'BACKEND': 'channels_redis.core.RedisChannelLayer',
'CONFIG': {
'hosts': [('127.0.0.1', 6379)],
},
},
}
asgi.py
Create an asgi.py
file in the root of your project, if it doesn’t already exist:
# asgi.py
import os
from channels.routing import ProtocolTypeRouter, URLRouter
from django.core.asgi import get_asgi_application
from channels.auth import AuthMiddlewareStack
from django.urls import path
from your_app_name import consumers
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'your_project_name.settings')
application = ProtocolTypeRouter({
"http": get_asgi_application(),
"websocket": AuthMiddlewareStack(
URLRouter(
[
path('ws/refresh/', consumers.RefreshConsumer.as_asgi()),
]
)
),
})
Create a consumer that handles WebSocket connections:
# consumers.py
import json
from channels.generic.websocket import AsyncWebsocketConsumer
class RefreshConsumer(AsyncWebsocketConsumer):
async def connect(self):
await self.channel_layer.group_add("refresh_group", self.channel_name)
await self.accept()
async def disconnect(self, close_code):
await self.channel_layer.group_discard("refresh_group", self.channel_name)
async def receive(self, text_data):
# This can be left empty since we're only sending messages from the server
pass
async def refresh(self, event):
await self.send(text_data=json.dumps({
'message': 'refresh'
}))
Create a view in your Django admin dashboard to trigger the refresh:
# views.py
from channels.layers import get_channel_layer
from asgiref.sync import async_to_sync
from django.http import HttpResponse
def trigger_refresh(request):
channel_layer = get_channel_layer()
async_to_sync(channel_layer.group_send)(
"refresh_group", {"type": "refresh"}
)
return HttpResponse("Frontend refresh triggered!")
Add a URL pattern for the view:
# urls.py
from django.urls import path
from your_app_name import views
urlpatterns = [
path('trigger-refresh/', views.trigger_refresh, name='trigger-refresh'),
]
Create an Angular service to handle WebSocket connections:
// websocket.service.ts
import { Injectable } from "@angular/core";
import { WebSocketSubject } from "rxjs/webSocket";
@Injectable({
providedIn: "root",
})
export class WebSocketService {
private socket$: WebSocketSubject<any>;
constructor() {
this.socket$ = new WebSocketSubject("ws://localhost:8000/ws/refresh/");
}
public get messages$() {
return this.socket$.asObservable();
}
}
In your Angular component, subscribe to the WebSocket service to listen for refresh messages:
// app.component.ts
import { Component, OnInit } from "@angular/core";
import { WebSocketService } from "./websocket.service";
@Component({
selector: "app-root",
templateUrl: "./app.component.html",
styleUrls: ["./app.component.css"],
})
export class AppComponent implements OnInit {
constructor(private webSocketService: WebSocketService) {}
ngOnInit() {
this.webSocketService.messages$.subscribe((message) => {
if (message.message === "refresh") {
window.location.reload();
}
});
}
}