Django Channels Postgres InterfaceError:连接已经关闭

Ken*_*ars 2 django postgresql pytest python-asyncio django-channels

我似乎无法解决这个问题。我正在按照文档中描述为我的频道消费者编写测试。我通常使用 Django 默认的 unittest,但由于 Channels 需要使用 pytest,我正在使用它,但仍然希望保持编写测试的类结构。

我在编写类似于 unittest 的设置方法时遇到了问题,我会用它来初始化测试属性。我尝试了使用autouse=true 的方法装置、类装置,但它们似乎都不起作用,因为我无法访问测试方法中的实例属性。最后我只是决定编写实例方法并为每个类手动调用它。这是我到目前为止:set_up

@pytest.mark.django_db
@pytest.mark.asyncio
class TestChatConsumer(object):

    @database_sync_to_async
    def set_up(self):

        self.user = UserFactory()
        self.api_client = APIClientFactory()
        self.token = TokenFactory(user=self.user)

        self.credentials = {
            'AUTHORIZATION': self.token.key,
            ...
        }

        self.credentials_params = '&'.join(['{}={}'.format(k, v) for k, v in self.credentials.items()])
        self.authless_endpoint = '/api/v1/ws/'
        self.endpoint = self.authless_endpoint + '?' + self.credentials_params

    async def test_connect_without_credentials(self):
        await self.set_up()
        communicator = WebsocketCommunicator(application, self.authless_endpoint)
        connected, subprotocol = await communicator.connect()
        assert not connected

    async def test_connect_with_credentials(self):
        await self.set_up()
        communicator = WebsocketCommunicator(application, self.endpoint)
        connected, subprotocol = await communicator.connect()
        assert connected
Run Code Online (Sandbox Code Playgroud)

问题是,psycopg2.InterfaceError: connection already closed当我的消费者尝试访问connect方法内的代码中的数据库时,我不断收到消息。database_sync_to_async当我手动测试它时,它使用并运行良好。

具体来说,connect引发错误的方法中的行如下所示:

await database_sync_to_async(user.inbox.increment_connections)().
Run Code Online (Sandbox Code Playgroud)

不确定问题究竟是什么,database_sync_to_async应该正确清理旧连接,以便可以正确创建新连接。

任何帮助将不胜感激。

Ken*_*ars 5

显然我看错了地方。问题出在这一行:

await database_sync_to_async(user.inbox.increment_connections)().

inbox是一个相关的管理器,所以它试图在实际之前获取它database_sync_to_async,但它失败了,因为它需要一个 db 调用。

我想这await database_sync_to_async(user).inbox.increment_connections()并没有工作,因为它包装的方法,而不是属性所以我落得这样做是利用prefetch_related获得inbox的认证过程。这样user.inbox就不再需要 db 调用,它工作正常