<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          實(shí)戰(zhàn) | 使用 Python 開發(fā)一個(gè)在線聊天室

          共 7240字,需瀏覽 15分鐘

           ·

          2021-09-24 16:17

          點(diǎn)擊上方“Python爬蟲與數(shù)據(jù)挖掘”,進(jìn)行關(guān)注

          回復(fù)“書籍”即可獲贈(zèng)Python從入門到進(jìn)階共10本電子書

          云想衣裳花想容,春風(fēng)拂檻露華濃。
          在線聊天室在如今的互聯(lián)網(wǎng)是一個(gè)很常見的產(chǎn)品,在各類電商的網(wǎng)頁客服中,我們都可以接觸到在線聊天。還有一個(gè)培訓(xùn)機(jī)構(gòu),你一打開他的網(wǎng)頁,立馬就彈出一個(gè)在線聊天框,防不勝防。
          今天州的先生給大家?guī)Я艘粋€(gè)后端 Python + 前端 Vue 的小項(xiàng)目教程。
          這個(gè)教程分為上中下三篇,其中:
          • 上篇使用 Django 傳統(tǒng)的 MTV 模式進(jìn)行開發(fā),實(shí)現(xiàn)一個(gè)在線聊天室的功能。

          • 中篇在上篇基礎(chǔ)上加入數(shù)據(jù)存儲(chǔ),實(shí)現(xiàn)聊天記錄的保存。

          • 下篇?jiǎng)t采用后端 Django + 前端 Vue 對(duì)傳統(tǒng)的 Web 模開發(fā)式進(jìn)行改造。

          非常適合學(xué)了 Django 之后寫項(xiàng)目無從下手的朋友們。
          本篇為上篇,我們將使用 Django 的傳統(tǒng)開發(fā)模式借助視圖和模板完成一個(gè)在線聊天室應(yīng)用的開發(fā)。
          最終效果如下所示:

          直接開干吧!

          創(chuàng)建虛擬環(huán)境

          為了不與計(jì)算機(jī)上現(xiàn)有的 Python 模塊沖突,我們新起一個(gè) Python 虛擬環(huán)境:
          1. python -m venv django3_env

          進(jìn)入虛擬環(huán)境,然后激活它。



          安裝依賴庫

          后端我們使用的是 Django3 框架(在本文編寫時(shí),Django 的最新版本為 3.2,所以我們不需要指定它的版本):
          1. pip install django

          還有一個(gè)重要的依賴庫——Channels。
          Channels 封裝了 Django 的原生異步視圖支持,讓 Django 項(xiàng)目不僅可以處理 HTTP,還可以處理需要長時(shí)間連接的協(xié)議,比如:WebSockets、MQTT、聊天機(jī)器人、業(yè)余無線電等等。
          簡而言之,就是為 Django 提供了異步和非 HTTP 處理的能力
          1. pip install channels

          因?yàn)?Channels 中的一個(gè)功能需要使用到 Redis 作為數(shù)據(jù)通道和緩存,所以我們得安裝 Redis 以及其 Python 相關(guān)的包。
          而 Redis 在 Windows 上沒有官方的支持,所以在這里,州的先生使用一個(gè) Redis 的替代品 Memurai 來當(dāng) Redis 使用:



          安裝完成后即會(huì)作為 Windows 的服務(wù)在后臺(tái)啟動(dòng)。
          然后安裝 Channels 的 Redis 配套庫:
          1. pip install channels_redis

          創(chuàng)建項(xiàng)目

          安裝好所有的依賴項(xiàng)之后,我們開始創(chuàng)建 Django 項(xiàng)目:
          1. django-admin startproject chat_backend

          然后進(jìn)入 chat_backend 目錄,創(chuàng)建一個(gè)應(yīng)用:
          1. python manage.py startapp chat

          配置項(xiàng)目

          接著我們進(jìn)行必要的配置,下述操作在 settings.py 文件中進(jìn)行。
          添加 channels、chat 應(yīng)用到 Django 項(xiàng)目的應(yīng)用列表:
          1. INSTALLED_APPS = [

          2. 'django.contrib.admin',

          3. 'django.contrib.auth',

          4. 'django.contrib.contenttypes',

          5. 'django.contrib.sessions',

          6. 'django.contrib.messages',

          7. 'django.contrib.staticfiles',

          8. 'channels',

          9. 'chat',

          10. ]

          在項(xiàng)目根目錄下新建名為templates的文件夾,然后定義 HTML 模板路徑:
            TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [ BASE_DIR / 'templates' ], 'APP_DIRS': True, 'OPTIONS': { 'context_processors': [ 'django.template.context_processors.debug', 'django.template.context_processors.request', 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', ], }, },]
            然后指定 asgi 應(yīng)用:
            1. ASGI_APPLICATION = "chat_backend.asgi.application"

            最后,指定 Channels 使用的數(shù)據(jù)通道后端,在這里我們使用的是 Redis:
              CHANNEL_LAYERS = { 'default': { 'BACKEND': 'channels_redis.core.RedisChannelLayer', 'CONFIG': { "hosts": [('127.0.0.1', 6379)], }, },}
              其中主機(jī)地址和端口號(hào)填寫 Redis 啟動(dòng)后顯示的默認(rèn)值。

              創(chuàng)建視圖

              在這個(gè)「在線聊天室」里面,一共有兩個(gè)頁面。一個(gè)是首頁,用于輸入房間號(hào)和用戶名;另一個(gè)則是聊天房間的頁面,用于進(jìn)行聊天。
              我們?cè)?chat 應(yīng)用的 views.py 下新建兩個(gè)視圖函數(shù):
                # 首頁def index(request): return render(request,'index.html',locals())# 聊天室def room(request,room_name): room_name = room_name username = request.GET.get('username', '游客') return render(request,'room.html',locals())
                其中,視圖函數(shù)index()返回 index.html,視圖函數(shù)room()返回 room.html,這兩個(gè) HTML 文件需要我們?cè)?code style="box-sizing: border-box;font-family: Consolas, "PingFang SC", Tahoma, "YaHei Consolas Hybrid";font-size: 14px;padding: 3px;margin-right: 4px;margin-left: 5px;background: rgb(246, 246, 246);border-radius: 3px;border-width: initial;border-style: none;border-color: initial;color: rgb(233, 30, 99) !important;">templates文件夾中進(jìn)行創(chuàng)建。

                定義路由

                視圖函數(shù)創(chuàng)建好之后,我們?yōu)槠浣壎酚桑?chat 應(yīng)用下新建一個(gè)名為urls.py的文件,在其中寫入如下內(nèi)容:
                  from django.urls import pathfrom chat.views import *# HTTP URLurlpatterns = [ path('',index,name="index"), path('<str:room_name>/',room,name="room")]
                  然后在 chat_backend 文件夾下的 urls.py 文件內(nèi)引入 chat 應(yīng)用的 url 配置:
                    urlpatterns = [ path('admin/', admin.site.urls), path('', include('chat.urls')),]
                    至此,「在線聊天室」這個(gè)項(xiàng)目的 HTTP 部分已經(jīng)完成了開發(fā)。
                    訪問首頁,會(huì)顯示如下圖所示的頁面:



                    我們可以輸入房間號(hào)和用戶名進(jìn)入房間,進(jìn)入房間后的頁面如下圖所示:



                    但是現(xiàn)在我們還不能進(jìn)行在線聊天,因?yàn)樵诰€聊天最核心的部分——WebSocket后端,我們還沒有編寫。

                    編寫 WebSocket 后端

                    WebSocket 是一個(gè)長連接的雙向通信協(xié)議。通過 WebSocket 我們可以在客戶端和服務(wù)器端之間建立實(shí)時(shí)的通信,而不是像 HTTP 那樣,只有客戶端發(fā)起,服務(wù)器端才會(huì)響應(yīng)。
                    在這里,我們借助 Channels 在 Django 中實(shí)現(xiàn) WebSocket。
                    首先,在 chat 應(yīng)用下新建一個(gè)名為consumers.py的文件(意為消費(fèi)者,是 Channels 中的一個(gè)重要概念),在其中,我們引入 WebSocket 類:
                    1. from channels.generic.websocket import AsyncWebsocketConsumer

                    然后繼承這個(gè)類,新建一個(gè)名為ChatConsumer的類,并在其中重寫 WebSocket 的連接、關(guān)閉連接、消息接收等方法,代碼如下所示:
                      class ChatConsumer(AsyncWebsocketConsumer): # 連接 async def connect(self): self.room_name = self.scope['url_route']['kwargs']['room_name'] self.room_group_name = 'chat_%s' % self.room_name # 加入聊天室 await self.channel_layer.group_add( self.room_group_name, self.channel_name ) await self.accept() # 關(guān)閉連接 async def disconnect(self, close_code): await self.channel_layer.group_discard( self.room_group_name, self.channel_name ) # async def receive(self, text_data=None, bytes_data=None): data = json.loads(text_data) message = data['message'] username = data['username'] # Send message to room group await self.channel_layer.group_send( self.room_group_name, { 'type': 'chat_message', 'message': message, 'username': username } ) # 接收消息 async def chat_message(self, event): message = event['message'] username = event['username'] # 發(fā)送消息到 Websocket await self.send(text_data=json.dumps({ 'message': message, 'username': username }))
                      最后,我們?cè)?asgi 中重新聲明路由。打開 chat_backend 目錄下的 asgi.py 文件,將內(nèi)容修改為如下所示:
                        import osfrom django.core.asgi import get_asgi_applicationfrom django.urls import pathfrom channels.auth import AuthMiddlewareStackfrom channels.routing import ProtocolTypeRouter, URLRouterfrom chat.consumers import ChatConsumeros.environ.setdefault('DJANGO_SETTINGS_MODULE', 'chat_backend.settings')application = ProtocolTypeRouter({ "http": get_asgi_application(), "websocket": AuthMiddlewareStack( URLRouter([ path("ws/<str:room_name>/",ChatConsumer.as_asgi()), ]) )})
                        如上代碼所示,HTTP 通過 get_asgi_application 以傳統(tǒng)的 HTTP 路由進(jìn)行處理,而 WebSocket 則通過 Channels 的 URLRouter 進(jìn)行處理。這樣我們的項(xiàng)目啟動(dòng)之后就可以同時(shí)支持 HTTP 訪問和 WebSocket 訪問。

                        前端連接 WebSocket

                        后端提供了 WebSocket 服務(wù),前端需要進(jìn)行連接和處理才行。
                        來看看前端的處理過程。
                        首先,通過 new 一個(gè) WebSocket對(duì)象,來創(chuàng)建 WebSocket連接:
                          // 建立一個(gè) websocket 連接 const chatSocket = new WebSocket( 'ws://' + window.location.host + '/ws/' + roomName + '/' );
                          然后編寫 WebSocket 各類事件的回調(diào)函數(shù):
                            // websocket連接關(guān)閉后的回調(diào)函數(shù) chatSocket.onclose = function(e) { console.error('The socket closed unexpectedly'); }; // websocket連接從服務(wù)器收到消息的回調(diào)函數(shù) chatSocket.onmessage = function(e) { const data = JSON.parse(e.data); if (data.message) { if(data.username == userName){ document.querySelector('#chat-record').innerHTML += ('<div class="right_msg">' + data.username + '<div class="right-record"><span>' + data.message + '</span></div></div><br>'); }else{ document.querySelector('#chat-record').innerHTML += ('<div class="left_msg">' + data.username + '<div class="left-record"><span>' + data.message + '</span></div></div><br>'); } } else { alert('消息為空!') } };
                            這樣前端就完成了對(duì)后端 WebSocket 的連接和消息接收。

                            最后

                            運(yùn)行項(xiàng)目,我們就可以在網(wǎng)頁上進(jìn)行實(shí)時(shí)在線聊天了。
                            當(dāng)然,現(xiàn)在這個(gè)項(xiàng)目還有很多問題,比如:
                            • 聊天記錄不會(huì)保存,刷新頁面之后聊天記錄就會(huì)消失。

                            • 沒有用戶認(rèn)證和鑒權(quán),誰都能輸入房間號(hào)和用戶名進(jìn)入聊天室。

                            接下來,讓我們繼續(xù)完善這個(gè)「在線聊天室」,敬請(qǐng)期待!

                            小伙伴們,快快用實(shí)踐一下吧!如果在學(xué)習(xí)過程中,有遇到任何問題,歡迎加我好友,我拉你進(jìn)Python學(xué)習(xí)交流群共同探討學(xué)習(xí)。

                            ------------------- End -------------------

                            往期精彩文章推薦:

                            歡迎大家點(diǎn)贊,留言,轉(zhuǎn)發(fā),轉(zhuǎn)載,感謝大家的相伴與支持

                            想加入Python學(xué)習(xí)群請(qǐng)?jiān)诤笈_(tái)回復(fù)【入群

                            萬水千山總是情,點(diǎn)個(gè)【在看】行不行

                            /今日留言主題/

                            隨便說一兩句吧~~

                            瀏覽 25
                            點(diǎn)贊
                            評(píng)論
                            收藏
                            分享

                            手機(jī)掃一掃分享

                            分享
                            舉報(bào)
                            評(píng)論
                            圖片
                            表情
                            推薦
                            點(diǎn)贊
                            評(píng)論
                            收藏
                            分享

                            手機(jī)掃一掃分享

                            分享
                            舉報(bào)
                            <kbd id="afajh"><form id="afajh"></form></kbd>
                            <strong id="afajh"><dl id="afajh"></dl></strong>
                              <del id="afajh"><form id="afajh"></form></del>
                                  1. <th id="afajh"><progress id="afajh"></progress></th>
                                    <b id="afajh"><abbr id="afajh"></abbr></b>
                                    <th id="afajh"><progress id="afajh"></progress></th>
                                    亚洲淫秽视频在线 | 日韩网站免费在线观看 | 操婷婷五月天 | 国产精品777777 | 少妇三角的黑森林的淫 |