當前位置:
首頁 > 最新 > Django Channel處理Websocket鏈接

Django Channel處理Websocket鏈接

關鍵時刻,第一時間送達!

GIF

在本教程中,我們會使用Django Channel創建一個實時更新用戶登錄登出列表的應用程序。

使用WebSockets在Django Channel框架下管理客戶端與伺服器之間的通訊,每當一個用戶獲得登錄許可,該事件會被廣播給每一個在線用戶。每一位用戶不用重新登錄就可以在屏幕上自動獲取實時發生的變化。

注意:我們建議你在開始閱讀本教程之前對Django有過使用經驗,因而你應該熟悉WebSockets的一些概念。

工具

我們製作該應用程序需要使用如下工具:

Python (v3.6.0)

Django (v1.10.5)

Django Channels (v1.0.3)

Redis (v3.2.8)

目標

完成本教程之後,我們能夠......

1.通過Django Channel將Web Sockets添加到Django的工程項目中

2.在Django和一個Redis伺服器之間創建一個簡單的連接

3.實現基本的用戶登錄驗證

4.每當一個用戶登錄或者登出的時候都會通過Django觸發反饋操作

準備工作

首先,創建一個新的虛擬環境獨立地來安裝項目的一些依賴。

然後,安裝Django,Django Channel和ASGI Redis,然後創建一個新的Django項目和應用程序。

注意:在實踐這個教程的過程中,我們會創建大量不同的文件和文件夾。如果你在什麼地方卡住了,請參考項目倉庫的文件結構。

接著,下載並安裝Redis。如果你的電腦是Mac系統,我們建議使用Homebrew來進行安裝:

接著,另外啟動一個終端來運行Redis伺服器程序,請確認程序運行默認埠號是6379,因為當我們要求Django與Redis交互的時候這個埠至關重要。完成如下更新項目setting.py文件中的INSTALLED_APPS之後初始化設置就完成了:

然後通過設置默認的BACKEND和ROUTING來配置CHANNEL_LAYERS

正如實驗所需,這裡使用Redis作為後端

WebSockets 101

通常情況下,Django使用HTTP協議來完成客戶端與伺服器的通訊:

1.客戶端給伺服器發送一個HTTP request

2.由Django來分析這個request,提取其中的URL,然後配對成一個視圖

3.由視圖處理請求之後將一個HTTP response返回給客戶端

說明:和HTTP協議不同的是,WebSockets協議允許雙向數據傳輸,也就是說伺服器可以在用戶不請求的情況下將數據傳輸給客戶端,而HTTP協議中只有發送request的客戶端才會接收到response。使用了WebSockets之後,伺服器可以同時和多台客戶端進行數據交互。在本教程中,我們使用前綴ws://來傳送WebSockets消息,以示區分於http://

注意:在入坑之前,請迅速瀏覽Channels Concepts的文檔

Consumers and Groups

創建第一個consumer用來處理客戶端與伺服器之間的基礎連接,在目錄example_channel/example目錄下新建一個文件叫作consumers.py,內容如下:

Consumers與Django的視圖相配對。每當有用戶連接到我們的應用程序,就會被添加到』users』組內,並且會接收到伺服器發送的信息。當客戶端關閉與我們的應用程序的連接時,這個通道就會從組內移除,用戶將不再接收到來自伺服器的信息。接下來讓我們設置路由,這個操作和Django URL配置幾乎相同,在example_channels目錄下創建一個叫作routing.py的文件,將下述代碼添加進去:

因此我們用channel_routing代替了urlpatterns,用route()代替了url()。此時我們發現comsumer函數已經和WebSockets關聯。

模板

我們來寫一些可以通過WebSocket來與伺服器進行數據傳輸的HTML代碼,在example_channels/example目錄下遞歸創建templates/example,最後構成目錄」example_channels/example/templates/example」。HTML代碼如下:

現在,客戶端已經用WebSocket打開一個與伺服器的連接,控制台會列印確認信息。

視圖

1.在example_channels/example/views.py文件中設置一個支持Django視圖來遞交template

2.將URL添加到example_channels/example/urls.py文件中:

3.在example_channels/example_channels/urls.py文件中同樣更新URL

測試

測試命令如下:

注意:可以在兩個不同的終端窗口運行python manage.py runserver –noworker和python manage.py runworker,來測試埠和worker服務作為獨立進程的運行結果。兩條命令都可實現,此時當你訪問http://localhost:8000/時你會看到終端列印的連接信息如下:

用戶驗證

既然我們已經證實我們可以打開一個連接,那麼我們下一步就是解決用戶驗證問題。記得我們的任務是:我們需要一種方式,使得每一個登錄到該應用程序的用戶都能夠看到一個包含所有用戶的列表。那麼我們首先需要給用提供一個創建賬號和登錄的方式。從創建一個簡單的登錄頁面開始,實現用戶通過用戶名和密碼進行驗證的登錄方式。在example_channels/example/templates/example目錄下創建一個叫作log_in.html的文件,內容如下:

然後,更新example_channels/example/views.py如下:

Django的表單結構支持常用的認證功能,我們使用AuthenticationForm來處理用戶登錄。這個表單結果檢查用戶提交的用戶名和密碼,然後如果可以找到一個有效用戶,就返回用戶對象。登錄有效的用戶對象之後將頁面重定向到主頁,為了用戶也可以能夠登出該應用程序,因此我們又創建了一個登出視圖來實現這一功能,登出後將用戶對象回退到登錄界面。更新example_channels/example/urls.py文件如下:

我們同時還需要一種方式來創建新用戶,和創建登錄頁面一樣,在文件夾example_channels/example/templates/example中創建一個叫作sign_up.html的新文件,由此來創建一個註冊頁面,該文件內容如下:

注意到,在登錄頁面有一個指向註冊頁面的鏈接,同時註冊頁面也有一個回退到登錄頁面的指針。將下列函數添加到視圖中:

我們使用另一個內建表單結構來創建用戶對象成功判斷表單有效後,我們將頁面重定向到登錄頁面,通過如下方式導入表單結構:

再次更新example_channels/exaple/urls.py文件如下:

此時我們需要創建一個用戶對象。運行伺服器程序之後,用瀏覽器訪問http://localhost:8000/sign_up,用有效的用戶名和密碼填寫表單,並提交數據來創建第一個用戶。

注意:用戶名michael,密碼johnson123

sign_up視圖將我們重定向到log_in視圖,在該視圖下我們可以認證我們新創建的用戶對象。我們登錄之後,可以測試新的認證視圖。使用註冊表單創建幾個新的用戶對象,為下一部分的工作做準備。

登錄提醒

我們已經能夠實現最基本的認證功能,但是我們還需要顯示包含用戶的列表,我們要求伺服器告訴用戶組該用戶什麼時候登錄,什麼時候登出。然後編寫consumer函數實現,用戶連接之後或者用戶斷開之前立刻發送一條信息。這些信息數據包括用戶的用戶名和運行狀態,更新example_channels/example/consumers.py文件如下:

注意:我們已經將裝飾器添加到函數,由此可以從Django獲得用戶對象。同時所有信息都必須是序列化JSON格式,因此我們必須把數據轉換成JSON字元串,接著按如下所示更新example_channels/example/templates/example/user_list.html文件:

在我們的主頁上,擴展了用戶列表來存放一個列表的用戶,我們存儲每一個用戶的用戶名作為一個數據屬性,由此可以容易地在DOM中找到用戶記錄。我們還針對WebSocket添加了一個事件監聽器,因此可以處理來自伺服器的信息。每當收到一條信息,我們就分析JSON數據,找到所指定用戶對應的

元素,並且更新該用戶的狀態。

由於Django是不監視用戶是否登錄的,因此我們需要創建一個簡單的模型來實現監視功能。在example_channels/example/models.py文件中,用一個連接到user模塊的一對一連接來創建一個LoggedInUser模型:

每當用戶登錄,應用程序就會創建一個LoggedInUser實例,並且用戶登出的時候,應用程序刪去該實例。

進行架構遷移的時候可以遷移資料庫適應變化。

然後,在example_channels/example/views.py文件中,更新用戶列表視圖,可以恢復用戶列表

如果一個用戶對象有一個關聯的LoggedInUser對象,那麼我們記錄這個用戶的狀態是』Online』,相反則用戶對象處於』Offline』狀態。我們還需要在用戶列表和登出視圖中添加一個@login_required裝飾器來達到僅限制於註冊用戶可以獲得。

此時用戶可以登錄或者登出,並且由此觸發伺服器向客戶端發送消息,但是我們無法知道當一個用戶第一次登錄的時候哪些用戶已經被記錄。用戶只能在另一個用戶狀態發生改變的時候看到更新,這裡就是LoggedInUser起作用的地方,但是我們需要一種方式當一個用戶登錄的時候創建一個LoggedInUser實例,然後在登出的時候進行銷毀。

Django庫有一個叫作signals的特色,會在特定事件發生的時候進行廣播通知。應用程序可以監聽這些通知並且按照廣播內容來做出響應,我們可以利用兩個較有用的內建signal(包括user_logged_in和user_logged_out)來處理LoggedInUser的行為。在example_channels/example目錄下創建一個新文件signals.py,內容如下:

我們應該在應用程序配置中獲得這些signals,配置example_channels/example/apps.py文件如下:

更新example_channels/example/__init__.py文件如下:

正確性檢查

現在我們完成了代碼編寫,讓一些用戶來連接我們的伺服器,從而測試我們的應用程序。

運行Django伺服器,用戶登錄並訪問主頁。我們可以看到包含應用程序中所有用戶的列表,其他用戶都處於』offline』狀態。然後打開一個新的匿名窗口,以另外一個用戶身份登錄,該用戶一登錄瀏覽器就將用戶的狀態為』Online』。從匿名窗口,我們也可以看到剛剛登錄的用戶也處於』Online』狀態。我們可以通過在不同的設備上讓不同的用戶登錄登出來測試WebSockets的健壯性。

通過在客戶端觀察開發控制台信息並且可以在終端查看伺服器運行情況。我們可以確認,當用戶登錄的時候WebSockets連接會形成,而用戶登出的時候則會被銷毀。

注意:你可以使用ngrok將本地伺服器安全地掛在互聯網上。這樣你就可以使用不同的移動終端比如手機,平板等,訪問本地伺服器了。

結束語

這片教程涵蓋了許多東西,包括Django Channels,WebSockets,用戶認證,信號,還有一些前端開發知識。主旨是想說明:Channels擴充了傳統的Django應用程序的功能,能夠從伺服器通過WebSockets將信息推送給多組用戶。它的功能非常強大。

想想此類的一些應用,比如我們可以創建聊天室,創建多人遊戲,創建能夠實現用戶實時交流的協作應用程序。甚至我們可以用WebSockets來優化一些常規任務,比如:伺服器會在完成任務之後給客戶端發送狀態更新,而不是時不時地查看伺服器,看一看一個長時運行的任務是否完成。

這個教程只是扒了一些Django Channel的一些簡單用法,查看Django Channel文檔可以查看其它可以實現的功能。

讀者可以從https://github.com/realpython/django-example-channels倉庫獲取項目的最終代碼。拜拜!!

來自:python程序員

譯者:thwcww

英文原文:https://realpython.com/blog/python/getting-started-with-django-channels/

Python開發整理髮布,轉載請聯繫作者獲得授權


喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 Python開發 的精彩文章:

使用Python自動提取內容摘要
多線程,理想和現實的差距!

TAG:Python開發 |