0

I use the API https://rapidapi.com/chicmi/api/chicmi-local-fashion/ and websockets in Django. I have an HTML form where I enter the number of days and maximum result, click a button, and nothing happens. When trying to open the page http://127.0.0.1:8000/events/London/, the browser also attempts to establish a WebSocket connection using the URL ws://127.0.0.1:8000/ws/London/, but the server cannot find a corresponding handler for this URL and returns a 404 error. So, I need to redirect the client to a page with fashion show data after the client enters data into the form. Please advise on how to fix the error.

[11/May/2023 20:55:04] "GET /events/London/ HTTP/1.1" 200 1676 Not Found: /ws/London/ [11/May/2023 20:55:04] "GET /ws/London/ HTTP/1.1" 404 4822

I tried to configure the paths correctly, but I still get an error

[11/May/2023 20:55:04] "GET /events/London/ HTTP/1.1" 200 1676 Not Found: /ws/London/ [11/May/2023 20:55:04] "GET /ws/London/ HTTP/1.1" 404 4822

My code

events.html

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Events</title>
    <script>
        var ws_url = 'ws://' + window.location.host + '/ws/' + '{{ city }}' + '/';
        var ws = new WebSocket(ws_url);
        ws.onmessage = function(event) {
            var event_data = JSON.parse(event.data)['event_data'];
            var event_list = document.getElementById('event-list');
            event_list.innerHTML = '';
            for (var i = 0; i < event_data.length; i++) {
                var event = event_data[i];
                var event_element = document.createElement('div');
                event_element.innerHTML = '<h2>' + event['event_name'] + '</h2>' +
                                          '<img src="' + event['event_preview_url'] + '">' +
                                          '<p><a href="' + event['detail_url'] + '">More Info</a></p>' +
                                          '<p>' + event['location'] + '</p>';
                event_list.appendChild(event_element);
            }
        };

        function update_events() {
            var days = document.getElementById('days').value;
            var max_results = document.getElementById('max-results').value;
            var message = {
                'days': days,
                'max_results': max_results
            };
            ws.send(JSON.stringify(message));
        }
    </script>
</head>
<body>
    <h1>Events in {{ city }}</h1>
    <p>Days: <input type="number" id="days" value="14"></p>
    <p>Max Results: <input type="number" id="max-results" value="5"></p>
    <button onclick="update_events()">Update</button>
    <div id="event-list"></div>
</body>
</html>

consumers.py

import json
from channels.generic.websocket import AsyncWebsocketConsumer
import requests

class EventConsumer(AsyncWebsocketConsumer):
    async def connect(self):
        self.city = self.scope['url_route']['kwargs']['city']
        await self.channel_layer.group_add(
            self.city,
            self.channel_name
        )
        await self.accept()

    async def disconnect(self, close_code):
        await self.channel_layer.group_discard(
            self.city,
            self.channel_name
        )

    async def receive(self, text_data):
        url = "https://chicmi.p.rapidapi.com/calendar_in_city/"
        headers = {
            "X-RapidAPI-Key": "d4ba369aa5msh31ba822955b0a7bp1c2147jsn0b48eb6cab4f",
            "X-RapidAPI-Host": "chicmi.p.rapidapi.com"
        }
        response = requests.get(url, headers=headers)
        data = response.json()
        events = data["values"]["events"]
        event_data = []
        for event in events:
            event_data.append({
                "event_name": event["event_name"],
                "event_preview_url": event["event_preview_url"],
                "detail_url": event["detail_url"],
                "location": event["location"]
            })
        await self.channel_layer.group_send(
            self.city,
            {
                'type': 'send_event_data',
                'event_data': event_data
            }
        )

    async def send_event_data(self, event):
        event_data = event['event_data']
        await self.send(json.dumps({
            'event_data': event_data
        }))

routing.py

from channels.routing import ProtocolTypeRouter, URLRouter
from django.urls import path
from . import consumers

websocket_urlpatterns = [
    path('ws/<str:city>/', consumers.EventConsumer.as_asgi()),
]


application = ProtocolTypeRouter({
    "websocket": URLRouter(websocket_urlpatterns)
})

fashionShows/urls

from django.urls import path
from . import views

urlpatterns = [
    path('events/<str:city>/', views.events, name='events'),
]

views.py

from django.shortcuts import render

def events(request, city):
    return render(request, 'events.html', {'city': city})

asgi.py


os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'semWork.settings')

application = get_asgi_application()

6
  • You need to move application from routing.py to asgi.py and make get_asgi_application() the http handler in ProtocolTypeRouter. See my answer here stackoverflow.com/a/68231046/8238485 Commented May 12, 2023 at 1:30
  • I fixed my asgi import os from channel.routing import Protocol Type Router, URL Router from django.core.asgi import get_asgi_application from fashionShows import routing os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'semWork.settings') application = ProtocolTypeRouter({ "http": get_asgi_application(), "websocket": URLRouter(routing.websocket_urlpatterns), }) but it still doesn't work Commented May 12, 2023 at 13:13
  • I can get a websocket connection with the code you have provided by starting a completely new project and making the change I suggested. The problem must be elsewhere in your configuration that you haven't specified. Your logs look like they come from nginx. Is your nginx configured to do a protocol switch to websocket? nginx.org/en/docs/http/websocket.html Commented May 12, 2023 at 22:38
  • It could be that the problem lies in the incorrect launch of your Django project. Could you please guide me on how to do it correctly and what needs to be added to my code to make it work like yours? I am new to Django and need to finish this project on time. Commented May 12, 2023 at 23:32
  • And if it's not too much trouble, is it possible to not use nginx? I want to simplify this code but keep the same functionality. Thank you for your help! Commented May 12, 2023 at 23:49

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.