最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Django Channels 實現(xiàn)點對點實時聊天和消息推送功能

 更新時間:2019年07月17日 13:56:59   作者:Suummmmer  
這篇文章主要介紹了Django Channels 實現(xiàn)點對點實時聊天和消息推送功能,本文分步驟給大家介紹的非常詳細,具有一定的參考借鑒價值,需要的朋友可以參考下

簡介在很多實際的項目開發(fā)中,我們需要實現(xiàn)很多實時功能;而在這篇文章中,我們就利用django channels簡單地實現(xiàn)了點對點聊天和消息推送功能。

手邊有一個項目需要用到后臺消息推送和用戶之間一對一在線聊天的功能。例如用戶A評論了用戶B的帖子,這時候用戶B就應該收到一條通知,顯示自己的帖子被評論了。這個功能可以由最基本的刷新頁面后訪問數(shù)據(jù)庫來完成,但是這樣會增加對后臺服務器的壓力,同時如果是手機客戶端的話,也會造成流量的損失。于是,我們考慮使用websocket建立一個連接來完成這個功能。

但是django并不支持websocket,因此在一番尋找之后發(fā)現(xiàn)了django-channels這個項目,它允許Django項目不僅可以處理HTTP,還可以處理需要長時間連接的協(xié)議 - WebSockets,MQTT,chatbots,業(yè)余無線電等等。

作者本人也接觸channels沒多久,為了搞這兩個功能看channels文檔看到自閉,最終簡單實現(xiàn)了這兩個功能,特地記錄一下

一:安裝channels

如果使用的是django 1.9 及以上,在pip安裝channels時可以不加-U參數(shù)

pip install channels

安裝結束后,我們把channels作為一個app添加進入我們的django項目,在settings.py中添加

INSTALLED_APPS = [
  'django.contrib.admin',
  'django.contrib.auth',
  'django.contrib.contenttypes',
  'django.contrib.sessions',
  'django.contrib.messages',
  'django.contrib.staticfiles',
  'Your-app',
  'channels',
]

在這里,我們使用redis做為channels的通道后端,以便支持更多的功能,具體涉及到的一些功能在后文中會提及。于是我們還需要安裝一些依賴包以支持其正常工作

pip install channels_redis

然后在settings.py文件中添加

CHANNEL_LAYERS = {
  "default": {
    "BACKEND": "channels_redis.core.RedisChannelLayer",
    "CONFIG": {
      "hosts": [('127.0.0.1', 6379)],
    },
    # 配置路由的路徑
    # "ROUTING": "exmchannels.routing.channel_routing",
  },
}
ASGI_APPLICATION = 'exmchannels.routing.application'

二:點對點聊天

在項目目錄下新建一個文件,用來存放我們的channels代碼,為channel。在channel中新建一個comsumers.py文件,在其中新建一個ChatComsumer類用來處理我們聊天時的websocket請求。相對于建立一個聊天室,在這里不同的是我們在ChatComsumer中添加了一個chats來記錄每一個group中的連接數(shù)。以此根據(jù)這個連接數(shù)來判斷,聊天雙方是否都已連接進入該個聊天group。

同時,我們設定聊天組的命名形式為user_a的id加上下劃線_加上user_b的id,其中id值從小到大放置,例如:195752_748418

class ChatConsumer(AsyncJsonWebsocketConsumer):
  chats = dict()
  async def connect(self):
    self.group_name = self.scope['url_route']['kwargs']['group_name']
    await self.channel_layer.group_add(self.group_name, self.channel_name)
    # 將用戶添加至聊天組信息chats中
    try:
      ChatConsumer.chats[self.group_name].add(self)
    except:
      ChatConsumer.chats[self.group_name] = set([self])
    #print(ChatConsumer.chats)
    # 創(chuàng)建連接時調用
    await self.accept()
  async def disconnect(self, close_code):
    # 連接關閉時調用
    # 將關閉的連接從群組中移除
    await self.channel_layer.group_discard(self.group_name, self.channel_name)
    # 將該客戶端移除聊天組連接信息
    ChatConsumer.chats[self.group_name].remove(self)
    await self.close()

ChatComsumer中的chats是一個字典,用來記錄每一個group中的連接數(shù)目。每當一個客戶端訪問正確的websocket url之后,都會調用connect()函數(shù),將該客戶端添加入其url中指向的一個group,同時向chats中添加該客戶端的信息。當該客戶端斷開連接時,會調用disconnect()函數(shù),將該客戶端從group中移除,同時刪除它在chats中的記錄。

完成了連接和斷開連接的處理之后,我們來進行接收信息的處理

 async def receive_json(self, message, **kwargs):
    # 收到信息時調用
    to_user = message.get('to_user')
    # 信息發(fā)送
    length = len(ChatConsumer.chats[self.group_name])
    if length == 2:
      await self.channel_layer.group_send(
        self.group_name,
        {
          "type": "chat.message",
          "message": message.get('message'),
        },
      )
    else:
      await self.channel_layer.group_send(
        to_user,
        {
          "type": "push.message",
          "event": {'message': message.get('message'), 'group': self.group_name}
        },
      )
  async def chat_message(self, event):
    # Handles the "chat.message" event when it's sent to us.
    await self.send_json({
      "message": event["message"],
    })

在上述函數(shù)中,我們可以看到,當接收到來自客戶端的websocket信息之后,我們首先判斷一下,這個聊天組中客戶端連接個數(shù)是一個還是兩個。如果連接個數(shù)為2,說明聊天雙方都已經連接到了該聊天組,因此可以直接向該group發(fā)送信息,這樣對方就可以直接收到信息;如果連接個數(shù)為1,說明信息接受者還未進入聊天組,我們便向其推送一條信息,包含group_name和信息內容。

就這樣,我們完成了一個點對點的聊天系統(tǒng)。

三:消息推送

消息推送工作原理大致上和聊天的原理一致,即每一個用戶都有屬于自己的一個websocket連接,這里我們可以使用其username作為group_name,當其他用戶的某些行為觸發(fā)了推送條件時,后臺便向該用戶所在的group發(fā)送一條信息,這樣就完成了消息推送服務。

再次,特地說明一下,channels同樣提供了單通道發(fā)送,即每一個客戶端連接時都會生成一個專門的通道名稱。但是我們在這里使用的全部都是group發(fā)送,一個原因是我個人比較懶,使用group便可以完成相應的功能,只要在客戶端連接時添加用戶認證,便能保證每個用戶只能連接上自己的那個group。當然,在這里只是展示簡單的消息推送如何實現(xiàn),并不展示其他代碼。

# 推送consumer
class PushConsumer(AsyncWebsocketConsumer):
  async def connect(self):
    self.group_name = self.scope['url_route']['kwargs']['username']
    await self.channel_layer.group_add(
      self.group_name,
      self.channel_name
    )
    await self.accept()
  async def disconnect(self, close_code):
    await self.channel_layer.group_discard(
      self.group_name,
      self.channel_name
    )
    # print(PushConsumer.chats)
  async def push_message(self, event):
    print(event)
    await self.send(text_data=json.dumps({
      "event": event['event']
    }))

消息推送是后臺向客戶端推送信息,因此不涉及處理接受來自客戶端的信息的操作,因此我們只要改寫connect()、disconnect()函數(shù),然后添加一個對發(fā)送信息的處理函數(shù)push_message()

然后我們再寫一個push()函數(shù),用來在項目的其他地方調用,這就是為什么我們在第一步里面要使用redis做為channels的通道后端。

from channels.layers import get_channel_layer

def push(username, event):
  channel_layer = get_channel_layer()
  async_to_sync(channel_layer.group_send)(
    username,
    {
      "type": "push.message",
      "event": event
    }
  )

這個函數(shù)寫在PushComsumer之外,因為我們在項目的其他地方調用時,不會使用self.self.channel_layer來獲取通道層,因此單獨寫做一個函數(shù),然后使用get_channel_layer來檢索它。

因此,在我們需要使用消息推送的地方,只要直接調用push()函數(shù),傳入被推送用戶的用戶名和推送的信息就OK了。

四:routing配置和其他配置

同樣,在channel文件夾下新建一個routing.py文件,然后在其中添加以下內容,其工作原理和django的urls.py一致,是websocket的連接路徑。

from . import consumers

websocket_urlpatterns = [
  url(r'^ws/chat/(?P<group_name>[^/]+)/$', consumers.ChatConsumer),
  url(r'^push/(?P<username>[0-9a-z]+)/$', consumers.PushConsumer),
]

然后在settings.py同目錄新建一個routing.py文件,在其中添加以下代碼

from channels.auth import AuthMiddlewareStack
from channels.routing import ProtocolTypeRouter, URLRouter
import example.routing

application = ProtocolTypeRouter({
  # (http->django views is added by default)
  'websocket': AuthMiddlewareStack(
    URLRouter(
      example.routing.websocket_urlpatterns
    )
  ),
})

這樣,客戶端便可以成功連接到websocket了,功能簡單實現(xiàn)。

總結

以上所述是小編給大家介紹的Django Channels 實現(xiàn)點對點實時聊天和消息推送功能,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對腳本之家網站的支持!
如果你覺得本文對你有幫助,歡迎轉載,煩請注明出處,謝謝!

相關文章

  • PyCharm最新激活碼(2020/10/27全網最新)

    PyCharm最新激活碼(2020/10/27全網最新)

    Pycharm最新激活碼全網最新(2020/10/27更新),適用Intellij idea 2020.2.x,WebStorm 2020.2.x,Pycharm 2020.2.x
    2020-10-10
  • python采集百度百科的方法

    python采集百度百科的方法

    這篇文章主要介紹了python采集百度百科的方法,涉及Python正則匹配及頁面抓取的相關技巧,需要的朋友可以參考下
    2015-06-06
  • Python操作Sql Server 2008數(shù)據(jù)庫的方法詳解

    Python操作Sql Server 2008數(shù)據(jù)庫的方法詳解

    這篇文章主要介紹了Python操作Sql Server 2008數(shù)據(jù)庫的方法,結合實例形式分析了Python使用pyodbc庫操作Sql Server 2008數(shù)據(jù)庫的連接、執(zhí)行sql語句、關閉連接等相關操作技巧與注意事項,需要的朋友可以參考下
    2018-05-05
  • Python subprocess模塊常見用法分析

    Python subprocess模塊常見用法分析

    這篇文章主要介紹了Python subprocess模塊常見用法,結合實例形式分析了subprocess模塊進程操作相關使用技巧與注意事項,需要的朋友可以參考下
    2018-06-06
  • python 密碼加密與解密的實現(xiàn)

    python 密碼加密與解密的實現(xiàn)

    本文主要介紹了python 密碼加密與解密的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2023-02-02
  • Django models.py應用實現(xiàn)過程詳解

    Django models.py應用實現(xiàn)過程詳解

    這篇文章主要介紹了Django models.py應用實現(xiàn)過程詳解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2019-07-07
  • Python 高級變量之字典和字符串詳解

    Python 高級變量之字典和字符串詳解

    這篇文章主要為大家介紹了Python 字典和字符串,具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2021-12-12
  • Python數(shù)據(jù)分析中Groupby用法之通過字典或Series進行分組的實例

    Python數(shù)據(jù)分析中Groupby用法之通過字典或Series進行分組的實例

    下面小編就為大家分享一篇Python數(shù)據(jù)分析中Groupby用法之通過字典或Series進行分組的實例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2017-12-12
  • 詳解Django-channels 實現(xiàn)WebSocket實例

    詳解Django-channels 實現(xiàn)WebSocket實例

    這篇文章主要介紹了詳解Django-channels實現(xiàn)WebSocket實例,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2019-08-08
  • Python PyQt5實戰(zhàn)項目之文件拷貝器的具體實現(xiàn)詳解

    Python PyQt5實戰(zhàn)項目之文件拷貝器的具體實現(xiàn)詳解

    PyQt5以一套Python模塊的形式來實現(xiàn)功能。它包含了超過620個類,600個方法和函數(shù)。本篇文章手把手帶你用PyQt5實現(xiàn)一個簡單的文件拷貝器,大家可以在過程中查缺補漏,提升水平
    2021-11-11

最新評論

呈贡县| 霍林郭勒市| 青田县| 正宁县| 兴安盟| 灌阳县| 伊宁市| 蒙自县| 石楼县| 新建县| 舒城县| 嵊州市| 池州市| 禄丰县| 永寿县| 巩留县| 荔波县| 巨鹿县| 麻江县| 公安县| 华宁县| 灵寿县| 桓台县| 通渭县| 兴山县| 岳池县| 纳雍县| 兰溪市| 平果县| 崇仁县| 余江县| 达孜县| 当雄县| 大宁县| 扎兰屯市| 崇仁县| 丰城市| 疏附县| 尼木县| 锡林浩特市| 龙口市|