如何将我知道其ID的用户添加到Django Channels channel_layer组? [英] How can I add a user whose ID I know to a Django Channels channel_layer group?
问题描述
我正在使用django-channels中的websocket编写一个Web应用程序。其中:
I am writing a web-application using websockets from django-channels. In which:
- 客户用户可以从商店用户下订单。
- 当用户请求通过他们的沟通者订购,我使用订单的ID创建了一个渠道组。
- 与此订单相关的商店也应添加到此渠道组。 这是我正在努力实现的目标。
- Customer users can make orders from store users.
- When a user requests an order via their communicator, I create a channel group using the order's id.
- The store related to this order should be added to this channel group as well. This is what I'm struggling to achieve.
在我的pytest中可以看到以下逻辑:
This logic can be seen in my pytest below:
async def test_store_is_added_to_order_group_on_create(self, settings):
customer = await create_customer()
store = await create_store()
product = await create_product(store=store)
store_communicator = await auth_connect(store)
# Log in as customer and create order
customer_communicator = await auth_connect(user)
await communicator.send_json_to({
'type': 'create.order',
'data': {
'product': str(product.id),
'customer': user.id
}
})
response = await communicator.receive_json_from()
data = response.get('data')
await communicator.disconnect()
# Send JSON message to new order's group.
order_id = data['id']
message = {
'type': 'echo.message',
'data': 'This is a test message.'
}
channel_layer = get_channel_layer()
await channel_layer.group_send(order_id, message=message)
# Store should receive JSON message from server.
response = await store_communicator.receive_json_from()
assert_equal(message, response)
await communicator.disconnect()
通信器函数create_order应该创建一个新的channel_layer组,在该组中应同时添加客户和商店
The communicator function create_order should create a new channel_layer group to which both the customer and store should be added.
async def create_order(self, event):
order = await self._create_order(event.get('data'))
order_id = f'{order.id}'
# Add the customer to a group identified by order's key value.
await self.channel_layer.group_add(
group=order_id,
channel=self.channel_name
)
# Confirm creation to customer.
await self.send_json({
'type': 'MESSAGE',
'data': order_data
})
理想情况下,我想在此将group_add设置为商店通信者的信道,但我不知道商店的信道名。 是否可以通过用户的传播者实例来了解商店的频道名称?
Ideally, I want to call group_add with channel set to the store communicator's channel here but I do not know the store's channel name. Is there a way to know the store's channel name from the user's communicator instance?
I已经采取了一种变通方法,在该方法中,我在上述send_json 之前将消息发送到商店的传播者如下:
I have made a workaround in which I send a message to the store's communicator BEFORE the above send_json as follows:
# HACK: Send notification to store
await self.channel_layer.group_send(group=store_group, message={
'type': 'notify.store',
'data': order_data
})
这将为商店调用第二个简单的通讯器功能:
This calls a second simple communicator function for the store:
async def notify_store(self, event):
data = event.get('data')
await self.channel_layer.group_add(
group=data['id'],
channel=self.channel_name
)
此替代方法无效。发送第二个echo.message后,会将存储添加到组中。 await self.channel_layer.group_send ...不会等到第二个传播者执行notify_store。有没有办法保证这种行为?
This workaround does not work. The store is added to the group after the second echo.message is sent. The await self.channel_layer.group_send... does not wait until notify_store has been executed for the second communicator. Is there a way to guarantee this behaviour?
还是有完全不同的方法来添加不同的方法用户从一个用户的通讯员转到channel_layer组?
谢谢您的时间。
推荐答案
我认为您已经知道需要做什么。您可以为商店指定一个小组,唯一的工作就是获取表示订阅此订购小组的消息。
I think you have the idea of what you need to do. You can have a group for the store and it's only job is to get messages that say subscribe to this order group.
但是,有些事情您不是不要考虑商店不在线怎么办。然后,您的客户的连接将永远被阻止。在asyncio中阻止这样的未来并不是很常见。如果要这样做,则需要创建一个任务。通常,您不会等待其他用户的会话发回响应。使它基于事件,并尽快将控制权交还给事件循环。
However, there are a few things that you aren't considering like what if the store isn't online. Then your customer's connection will block forever. Blocking on a future like that isn't very common with asyncio. If you want to do that you need to create a task. Normally you wouldn't wait for another user's session to send a response back. Make it event based and give control back to the event loop as soon as possible.
希望像这样基于事件进行更多操作:
Look at doing it more event based like this:
- 发送消息告诉商店订阅
id的订单。 - 使用JavaScript setTimeout或异步任务处于异步睡眠状态的计算机最终将超时并退出所有组的订阅,并出现错误消息而断开连接。
- 让商店将消息发送到它所订阅的订单组。如果您
从商店收到消息,请取消超时并开始
进行通信。
您会发现这些东西很难测试,特别是如果您正在测试是否要接收响应。每个消息就像一个新请求。渠道确实需要更好的测试框架。因此,我的频道代码几乎没有任何测试。
You'll find that this stuff is kind of hard to test especially if you're testing for responses to be received. Each message is like a new request. Channels really needs a better testing framework. I have hardly any tests in my channels code because of this.
这篇关于如何将我知道其ID的用户添加到Django Channels channel_layer组?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!