Как мне связаться с веб-сокетом в запросе Django API GET? - PullRequest
0 голосов
/ 08 мая 2020

Я пытаюсь получить ответ от сервера websocket (реализованного с помощью websockets и asyncio) из метода Django REST API. Что-то вроде следующей структуры:

Django App

(This does not work, but illustrates the idea)

class AnAPI(views.APIView):

    async def get(self, request):
        try:
            timeout = 5
            try:
                ws_conn = await asyncio.wait_for(websockets.connect(WS_STRING), timeout)
            except ConnectionTimeoutError as e:
                 <.....>

            await ws_conn.send(...)
            response = await ws_conn.recv()
            ws_conn.close()
            return Response(...)
        except Exception as e:
            print(e)
            return Response(...)

WS Server

ws_server = websockets.serve(...)
asyncio.get_event_loop().run_until_complete(ws_server)
asyncio.get_event_loop().run_forever()

Очевидно, это заставляет метод Django GET возвращать <class 'coroutine'>

AssertionError: Expected a `Response`, `HttpResponse` or `HttpStreamingResponse` to be returned from the view, but received a `<class 'coroutine'>`

Любые указатели будут очень благодарны!


РЕДАКТИРОВАТЬ: Спасибо всем, кто ответил! Я искал легкое решение, поскольку это, вероятно, единственное место, где приложению Django необходимо взаимодействовать с сервером WS. В конце концов я принял решение @Joran, но упаковал все во вспомогательную функцию, примерно так:

class AnAPI(views.APIView):

    def get(self, request):
        loop = asyncio.new_event_loop()
        asyncio.set_event_loop(loop)
        result = loop.run_until_complete(my_async_helper_function())
        return Response(...)


async def my_async_helper_function():

    try:
            timeout = 5
            try:
                ws_conn = await asyncio.wait_for(websockets.connect(WS_STRING), timeout)
            except ConnectionTimeoutError as e:
                 <.....>

            await ws_conn.send(...)
            response = await ws_conn.recv()
            await ws_conn.close()
            return ...
        except Exception as e:
            print(e)
            await ws_conn.close()
            return ...


1 Ответ

1 голос
/ 08 мая 2020

вы не можете использовать asyn c с django ответами (я думаю ...)

вместо этого вы можете попробовать

import asyncio

class AnAPI(views.APIView):
    def get(self, request):
        try:
        timeout = 5
        loop = asyncio.new_event_loop()
        asyncio.set_event_loop(loop) 
        try:                
            ws_conn = loop.run_until_complete(websockets.connect(WS_STRING), timeout)               
        except ConnectionTimeoutError as e:
             <.....>

        loop.run_until_complete(ws_conn.send(...))
        response = loop.run_until_complete(ws_conn.recv())
        ws_conn.close()
        return Response(...)

в качестве альтернативы, я считаю, https://pypi.org/project/websocket_client/ предлагает неасинхронный c интерфейс, который очень прост в использовании

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...