如何正确从 Django Channels 向 React Frontend 发送响应?

问题描述 投票:0回答:1

我正在尝试使用 Django Channels 为 React 前端 Web 应用程序和 Django REST 后端实现长轮询。我相信我所拥有的大部分内容在某种程度上都有效,但某些东西必须错误配置或编码才能产生意想不到的结果。


UPDATE:看来问题出在

axios.get(...)
请求上。当用
fetch(...)
替换该请求时,该 fetch 每次都会收到一个响应,而 Axios 调用平均每隔一次都会收到一个响应。目前不确定解决方案。

简而言之,我收到的问题是,当 Django Channels Consumer 发回响应时,它不会立即返回到前端(按照代码中的
console.log(...)

);相反,消费者似乎必须发送另一个响应,然后前一个或两个响应都会出现在前端。

我正在尝试使用 

AsyncHttpConsumer

来实现,因为 Websockets 在我们的用例中是不可能的。

Asgi.py

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'project.settings') django_asgi_app = get_asgi_application() application = ProtocolTypeRouter( { "http": URLRouter( longpoll_urlpatterns + [re_path(r"", django_asgi_app)] ), } )

路由.py

longpoll_urlpatterns = [ # Tried using re_path but did not work path("analysisSubscription/<int:analysisId>/", consumers.AnalysisConsumer.as_asgi()), ]

消费者.py

class AnalysisConsumer(AsyncHttpConsumer): async def handle(self, body): print("In Handle") print(self.scope) self.analysisId = self.scope["url_route"]["kwargs"]["analysisId"] self.analysis_group_name = f"analysis_{self.analysisId}" # Register with the appropriate channel await self.channel_layer.group_add(self.analysis_group_name, self.channel_name) await self.send_headers(headers=[ (b"Content-type", b"application/json"), (b"Access-Control-Allow-Origin", b"*"), (b"Access-Control-Allow-Headers", b"Origin, X-Requested-With, Content-Type, Accept, Authorization"),]) #The server won't send the headers unless we start sending the body await self.send_body(b"", more_body=True) print("Registered consumer for ID: ", self.analysisId, " and group: ", self.analysis_group_name) # await self.channel_layer.group_send(self.analysis_group_name, {"type": "analysis.update", "text": self.analysisId}) async def http_request(self, message): print("In Request") print(message) if "body" in message: self.body.append(message["body"]) if not message.get("more_body"): try: await self.handle(b"".join(self.body)) except: print("Stopping") # If something goes wrong, disconnect # In the parent this ALWAYS disconnects and thus long-polling breaks await self.disconnect() raise StopConsumer() async def disconnect(self): print("Disconnecting!") await self.channel_layer.group_discard(self.analysis_group_name, self.channel_name) async def analysis_update(self, event): print(event) print("Inside Analysis Consumer") analysisId = event['id'] analysisData = "" try: analysisData = await self.getAnalysis(analysisId) analysisData = json.dumps(analysisData) except Exception as ex: print("Failed to retrieve Analysis object: {ex}") return print("Retrieved analysis:\n\t", analysisData) await self.send_body(analysisData.encode('utf-8')) print("Sent the response") await asyncio.sleep(1) await self.http_disconnect(None) @database_sync_to_async def getAnalysis(self, id): return AnalysisSerializer(Analysis.objects.filter(id=id)[0]).data

然后,在更新 Analysis 期间,在 Views.py 文件中,我调用以下行与 Consumer 组进行通信,并调用之前定义的函数 
analysis_update

async_to_sync(layers.group_send)(f"analysis_{idAnalysis}", {"type": "analysis.update", "id": idAnalysis})

前端 ReactJS 代码基本上通过执行以下操作并检查
response

来循环。

await axios.get(ApiUrl.analysisSubscribe(analysisId), {
            timeout: 60000,
        })


python reactjs axios fetch-api django-channels
1个回答
0
投票
GET

请求在

OPTIONS
之前发送
GET
方法请求以获取信息。
自从这个问题以来,我转而采用了使用 

fetch

Axios
来请求的替代路线。在调试任务的另一个问题时,我们偶然发现
fetch
请求实际上是在发送
OPTIONS
请求之前发送
GET
方法请求。
查看 Axios 是否也会发生这种情况,似乎确实如此(并且已通过测试得到证实)。有关更多信息,请参阅 

AXIOS 请求方法更改为“OPTIONS”而不是“GET”。

© www.soinside.com 2019 - 2024. All rights reserved.