簡體   English   中英

如何將我知道其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應用程序。 其中:

  1. 客戶用戶可以從商店用戶下訂單。
  2. 當用戶通過通信器請求訂單時,我將使用訂單的ID創建一個渠道組。
  3. 與該訂單相關的商店也應添加到該渠道組。 這就是我正在努力實現的目標。

在我的pytest中可以看到以下邏輯:

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組,客戶和商店都應添加到該組。

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設置為商店通信者的信道,但我不知道商店的信道名。 有沒有一種方法可以從用戶的通信器實例中了解商店的渠道名稱?


我做了一個變通辦法, 在上述send_json之前 ,我將消息發送到商店的通信 ,如下所示:

    # HACK: Send notification to store
    await self.channel_layer.group_send(group=store_group, message={
        'type': 'notify.store',
        'data': order_data
    })

這將為商店調用第二個簡單的通信器函數:

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。 有沒有辦法保證這種行為?


還是有一種完全不同的方法來將一個用戶的通信者添加到不同用戶的channel_layer組中?

感謝您的時間。

我認為您已經知道需要做什么。 您可以為商店設置一個組,唯一的工作就是獲取表示訂閱此訂單組的消息。

但是,您沒有考慮一些事情,例如商店不在線時的情況。 然后,您的客戶的連接將永遠被阻止。 在asyncio中阻止這樣的未來並不是很常見。 如果要這樣做,則需要創建一個任務。 通常,您不會等待其他用戶的會話發回響應。 使它基於事件,並盡快將控制權交還給事件循環。

看看這樣做是基於以下更多事件:

  • 發送消息,告知商店訂閱訂單ID。
  • 在JavaScript setTimeout或具有asyncio睡眠的asyncio任務中,它最終都會超時並退訂所有組,並顯示一條錯誤消息,從而斷開連接。
  • 讓商店向其訂閱的訂單組發送一條消息。 如果您從商店收到消息,請取消超時並開始交流。

您會發現這些東西很難測試,尤其是當您要測試是否要收到響應時。 每個消息就像一個新請求。 渠道確實需要更好的測試框架。 因此,我的頻道代碼幾乎沒有任何測試。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM