Учебник, часть 1. Базовая настройка

В этом уроке мы создадим простой чат-сервер. Он будет иметь две страницы:

  • Индексное представление, которое позволяет вам ввести имя комнаты чата, чтобы присоединиться.

  • Представление для комнаты, которое позволяет видеть сообщения, опубликованные в определенной комнате чата.

Представление комнаты будет использовать WebSocket для связи с сервером Django и прослушивания любых сообщений, которые публикуются.

Мы предполагаем, что вы знакомы с основными понятиями для создания сайта Django. Если нет, мы рекомендуем сначала ознакомиться с учебником по Django, а затем вернуться к этому учебнику.

Мы предполагаем, что у вас уже установлен Django. Вы можете узнать, какой Django установлен и какая версия установлена, выполнив следующую команду в приглашении оболочки (обозначено префиксом $):

$ python3 -m django --version

Мы также предполагаем, что у вас уже есть установленый Channels. Вы можете узнать, что Channels установлены, выполнив следующую команду:

$ python3 -c 'import channels; print(channels.__version__)'

Это руководство написано для Channels 3.0, которые поддерживают Python 3.6+ и Django 2.2+. Если версия Channels не совпадает, вы можете обратиться к руководству для своей версии Channels, используя переключатель версий в нижнем левом углу этой страницы, или обновить каналы до последней версии.

В этом руководстве также используется Docker для установки и запуска Redis. Мы используем Redis в качестве резервного хранилища для слоя канала, который является необязательным компонентом библиотеки Channels, которую мы используем в руководстве. Установите Docker с официального веб-сайта - есть официальные среды выполнения для Mac OS и Windows, которые упрощают его использование, и пакеты для многих дистрибутивов Linux, где он может работать нативно.

Примечание

В то время как вы можете запускать стандартный Django runserver без необходимости в Docker’е, функциям каналов, которые мы будем использовать в последующих частях учебника, потребуется Redis для запуска, и мы рекомендуем Docker как самый простой способ сделать это.

Создание проекта

Если у вас еще нет проекта Django, вам нужно будет его создать.

Выполните в терминале в командной строке cd: смену каталога на тот, в котором вы хотите хранить код проекта, затем запустите следующую команду:

$ django-admin startproject mysite

Это создаст в вашем текущем каталоге каталог mysite со следующим содержимым:

mysite/
    manage.py
    mysite/
        __init__.py
        asgi.py
        settings.py
        urls.py
        wsgi.py

Примечание

Django 2.2 не будет иметь файла asgi.py. Не волнуйтесь, вы сможете создать его в ближайшее время.

Создание приложения чата

Мы поместим код для сервера чата в собственное приложение.

Убедитесь, что вы находитесь в том же каталоге, что и manage.py и введите эту команду:

$ python3 manage.py startapp chat

Это создаст каталог chat, который будет выглядеть следующим образом:

chat/
    __init__.py
    admin.py
    apps.py
    migrations/
        __init__.py
    models.py
    tests.py
    views.py

В данном руководстве мы будем работать только с chat/views.py и chat/__ init __.py. Поэтому удалите все остальные файлы из каталога chat.

После удаления ненужных файлов каталог chat должен иметь вид:

chat/
    __init__.py
    views.py

Нам нужно сообщить нашему проекту, что приложение chat установлено. Отредактируйте файл mysite/settings.py и добавьте 'chat' в параметр INSTALLED_APPS. Это будет выглядеть следующим образом:

# mysite/settings.py
INSTALLED_APPS = [
    'chat',
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
]

Добавление представление индексной страницы

Теперь мы создадим первое, индексное представление, которое позволит вам ввести имя комнаты чата, в которую вы хотите вступить.

Создайте каталог templates в каталоге chat. В каталоге templates, который вы только что создали, создайте еще один каталог с именем chat, и в нем создайте файл с именем index.html для хранения шаблона для представления индексной страницы.

Теперь ваш каталог чата должен выглядеть следующим образом:

chat/
    __init__.py
    templates/
        chat/
            index.html
    views.py

Поместите следующий код в chat/templates/chat/index.html:

<!-- chat/templates/chat/index.html -->
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8"/>
    <title>Chat Rooms</title>
</head>
<body>
    What chat room would you like to enter?<br>
    <input id="room-name-input" type="text" size="100"><br>
    <input id="room-name-submit" type="button" value="Enter">

    <script>
        document.querySelector('#room-name-input').focus();
        document.querySelector('#room-name-input').onkeyup = function(e) {
            if (e.keyCode === 13) {  // enter, return
                document.querySelector('#room-name-submit').click();
            }
        };

        document.querySelector('#room-name-submit').onclick = function(e) {
            var roomName = document.querySelector('#room-name-input').value;
            window.location.pathname = '/chat/' + roomName + '/';
        };
    </script>
</body>
</html>

Создайте функцию представления для представления комнаты. Поместите следующий код в chat/views.py:

# chat/views.py
from django.shortcuts import render

def index(request):
    return render(request, 'chat/index.html')

Чтобы вызвать представление, нам нужно сопоставить его с URL - и для этого нам нужен URLconf.

Чтобы создать URLconf в каталоге чата, создайте файл с именем urls.py. Теперь каталог вашего приложения должен выглядеть следующим образом:

chat/
    __init__.py
    templates/
        chat/
            index.html
    urls.py
    views.py

В файл chat/urls.py включите следующий код:

# chat/urls.py
from django.urls import path

from . import views

urlpatterns = [
    path('', views.index, name='index'),
]

Следующий шаг - указать корневой URLconf на модуль chat.urls. В mysite/urls.py добавьте импорт для django.conf.urls.include и вставьте include() в список urlpatterns, чтобы у вас были:

# mysite/urls.py
from django.conf.urls import include
from django.urls import path
from django.contrib import admin

urlpatterns = [
    path('chat/', include('chat.urls')),
    path('admin/', admin.site.urls),
]

Давайте проверим, что представление индекса работает. Выполните следующую команду:

$ python3 manage.py runserver

Вы увидите следующий вывод в командной строке:

Watching for file changes with StatReloader
Performing system checks...

System check identified no issues (0 silenced).

You have 18 unapplied migration(s). Your project may not work properly until you apply the migrations for app(s): admin, auth, contenttypes, sessions.
Run 'python manage.py migrate' to apply them.
October 21, 2020 - 18:49:39
Django version 3.1.2, using settings 'mysite.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.

Перейдите на страницу http://127.0.0.1:8000/chat/ в своем браузере — вы должны увидеть текст «What chat room would you like to enter??» наряду с вводом текста, чтобы ввести название комнаты.

Введите «lobby» в качестве названия комнаты и нажмите клавишу ввода. Вы будете перенаправлены в комнату по адресу http://127.0.0.1:8000/chat/lobby/, но мы еще не написали функцию комнаты, так что вы получите страницу с ошибкой «Page not found».

Перейдите в терминал, где вы выполнили команду runserver и нажмите Control-C, чтобы остановить сервер.

Интеграция библиотеки Channels

Пока что мы только создали обычное приложение Django; мы вообще не использовали библиотеку Channels. Теперь пришло время интегрировать ее.

Давайте начнем с создания конфигурации корневой маршрутизации для Channels. Channels routing configuration - это ASGI-приложение, которое похоже на Django URLconf, в том смысле, что оно указывает Channels, какой код запускать, когда HTTP-запрос поступает на сервер Channels.

Начните с корректировки файла mysite/asgi.py, включив в него следующий код:

# mysite/asgi.py
import os

from channels.routing import ProtocolTypeRouter
from django.core.asgi import get_asgi_application

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'mysite.settings')

application = ProtocolTypeRouter({
    "http": get_asgi_application(),
    # Just HTTP for now. (We can add other protocols later.)
})

Примечание

Django 2.2 не имеет встроенной поддержки ASGI, поэтому мы должны использовать альтернативу Channel. Создайте mysite/asgi.py следующим образом:

# mysite/asgi.py
import os

import django
from channels.http import AsgiHandler
from channels.routing import ProtocolTypeRouter

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'mysite.settings')
django.setup()

application = ProtocolTypeRouter({
  "http": AsgiHandler(),
  # Just HTTP for now. (We can add other protocols later.)
})

Теперь добавьте библиотеку Channels в список установленных приложений. Отредактируйте файл mysite/settings.py и добавьте 'channels' к параметру INSTALLED_APPS. Это будет выглядеть следующим образом:

# mysite/settings.py
INSTALLED_APPS = [
    'channels',
    'chat',
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
]

Вам также нужно будет указать Channels на корневую конфигурацию маршрутизации. Отредактируйте файл mysite/settings.py еще раз и добавьте в его нижнюю часть следующее:

# mysite/settings.py
# Channels
ASGI_APPLICATION = 'mysite.asgi.application'

Теперь, когда Channels есть в установленных приложениях, он получит контроль над командой runserver, заменив стандартный сервер разработки Django на сервер разработки Channels.

Примечание

Сервер разработки Channels будет конфликтовать с любыми другими сторонними приложениями, для которых требуется перегруженная или заменяющая команда runserver. Примером такого конфликта является whitenoise.runserver_nostatic из whitenoise. Чтобы решить такие проблемы, попробуйте переместить channel в верхнюю часть INSTALLED_APPS или полностью удалить приложение-нарушитель.

Давайте убедимся, что сервер разработки Channels работает правильно. Выполните следующую команду:

$ python3 manage.py runserver

Вы увидите следующий вывод в командной строке:

Watching for file changes with StatReloader
Performing system checks...

System check identified no issues (0 silenced).

You have 18 unapplied migration(s). Your project may not work properly until you apply the migrations for app(s): admin, auth, contenttypes, sessions.
Run 'python manage.py migrate' to apply them.
October 21, 2020 - 19:08:48
Django version 3.1.2, using settings 'mysite.settings'
Starting ASGI/Channels version 3.0.0 development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.

Примечание

Проигнорируйте предупреждение о непримененных миграциях базы данных. Мы не будем использовать базу данных в этом уроке.

Обратите внимание на строку, начинающуюся с Starting ASGI/Channels version 3.0.0 development server at http://127.0.0.1:8000/. Это указывает на то, что сервер разработки Channels сменил сервер разработки Django.

Перейдите на http://127.0.0.1:8000/chat/ в своем браузере, и вы все равно должны увидеть индексную страницу, которую мы создали ранее.

Перейдите в терминал, где вы выполнили команду runserver и нажмите Control-C, чтобы остановить сервер.

Этот учебник продолжается в Учебник, часть 2.

Вернуться на верх