Django Channels Postgres InterfaceError: connection already closed
Django Channels Postgres InterfaceError: connection already closed
我似乎无法解决这里的问题。我正在为 description in the docs 之后的频道消费者编写测试。我通常会使用 Django 默认的单元测试,但由于 Channels 需要使用 pytest,所以我正在使用它,但仍然希望保持编写测试的 class 结构。
我在编写类似于 unittest 的设置方法时遇到问题,我将使用它来初始化测试属性。我尝试了 method fixtures, class fixtures using autouse=true,但其中 none 似乎有效,因为我无法访问测试方法中的实例属性。最后我决定编写 set_up
实例方法并为每个 class 手动调用它。这是我目前所拥有的:
@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
问题是,当我的消费者尝试在 connect
方法内的代码中访问数据库时,我一直收到 psycopg2.InterfaceError: connection already closed
。它使用 database_sync_to_async
,当我手动测试它时效果很好。
具体来说,connect
方法中引发错误的行如下所示:
await database_sync_to_async(user.inbox.increment_connections)().
不确定问题到底是什么,因为 database_sync_to_async
应该正确清理旧连接,以便正确创建新连接。
非常感谢任何帮助。
显然我看错地方了。问题出在这一行:
await database_sync_to_async(user.inbox.increment_connections)()
.
inbox
是一个相关的管理器,因此它试图在实际 database_sync_to_async
之前获取它,但由于需要数据库调用而失败。
我尝试了这个 await database_sync_to_async(user).inbox.increment_connections()
但它没有用,因为它包装了一个方法,而不是一个属性,所以我最终做的是使用 prefetch_related
来获取 inbox
认证过程中。这样 user.inbox
不再需要数据库调用并且它工作正常
我似乎无法解决这里的问题。我正在为 description in the docs 之后的频道消费者编写测试。我通常会使用 Django 默认的单元测试,但由于 Channels 需要使用 pytest,所以我正在使用它,但仍然希望保持编写测试的 class 结构。
我在编写类似于 unittest 的设置方法时遇到问题,我将使用它来初始化测试属性。我尝试了 method fixtures, class fixtures using autouse=true,但其中 none 似乎有效,因为我无法访问测试方法中的实例属性。最后我决定编写 set_up
实例方法并为每个 class 手动调用它。这是我目前所拥有的:
@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
问题是,当我的消费者尝试在 connect
方法内的代码中访问数据库时,我一直收到 psycopg2.InterfaceError: connection already closed
。它使用 database_sync_to_async
,当我手动测试它时效果很好。
具体来说,connect
方法中引发错误的行如下所示:
await database_sync_to_async(user.inbox.increment_connections)().
不确定问题到底是什么,因为 database_sync_to_async
应该正确清理旧连接,以便正确创建新连接。
非常感谢任何帮助。
显然我看错地方了。问题出在这一行:
await database_sync_to_async(user.inbox.increment_connections)()
.
inbox
是一个相关的管理器,因此它试图在实际 database_sync_to_async
之前获取它,但由于需要数据库调用而失败。
我尝试了这个 await database_sync_to_async(user).inbox.increment_connections()
但它没有用,因为它包装了一个方法,而不是一个属性,所以我最终做的是使用 prefetch_related
来获取 inbox
认证过程中。这样 user.inbox
不再需要数据库调用并且它工作正常