Перед тем, как приступить к созданию моделей нашего чата, давайте установим следующие зависимости:
pip install channels
pip install daphne
Daphne — это сервер протоколов HTTP, HTTP2 и WebSocket для ASGI и ASGI-HTTP, разработанный для поддержки каналов Django.
INSTALLED_APPS = [
'channels',
'daphne'
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'accounts',
'chat'
]
Также нам необходимо добавить ASGI_APPLICATION для нашего приложения, для этого рядом с WSGI_APPLICATION добавим следующую строку:
WSGI_APPLICATION = 'django_channels_chat.wsgi.application'
ASGI_APPLICATION = 'django_channels_chat.asgi.application' # new
Теперь мы можем запустить наш сервер. Поскольку мы добавили channels и daphne в список INSTALLED_APP, он возьмет на себя обработку команды runserver и запустит сервер ASGI, а не сервер WSGI:
Модели чата
Для нашего приложения нам понадобятся три модели баз данных: Group, Message и Event.
- Модель
Groupбудет хранить всю информацию о групповом чате, такую как название группы и ее участников. - Модель
Messageбудет хранить информацию о сообщениях, которые были отправлены в группе. Информация будет включать отправителя сообщения, группу, которой оно было отправлено, отметку времени сообщения и содержание сообщения. - Модель
Eventбудет хранить информацию о пользователе, присоединяющемся к группе или покидающем ее, а также временную метку, когда он вступил или вышел.
Чтобы создать модели, откройте models.py файл и добавьте следующие классы моделей:
from django.db import models
from django.contrib.auth import get_user_model
from uuid import uuid4
from django.urls import reverse
User = get_user_model()
class Group(models.Model):
''' Групповая модель, в которой несколько пользователей могут делиться идеями и обсуждать их '''
uuid = models.UUIDField(default=uuid4, editable=False)
name = models.CharField(max_length=30)
members = models.ManyToManyField(User)
def __str__(self) -> str:
return f"Group {self.name}-{self.uuid}"
def get_absolute_url(self):
return reverse("group", args=[str(self.uuid)])
def add_user_to_group(self, user: User):
'''Вспомогательная функция для добавления пользователя в группу и создания объекта'''
self.members.add(user)
self.event_set.create(type="Join", user=user)
self.save()
def remove_user_from_group(self, user: User):
'''Функция для удаления членов группы, когда они выходят из группы чата'''
self.members.remove(user)
self.event_set.create(type="Left", user=user)
self.save()
Мы даем группе UUID, имя, а затем список участников, который в данном случае представлен объединением «многие-ко-многим» с существующей кастомной моделью User, которую мы реализовали в прошлом разделе.
Также мы добавили пару вспомогательных функций, с помощью которых у нас появилась возможность добавлять и удалять пользователя из группы.
Модель сообщения
Модель сообщения будет довольно простая и понятная:
class Message(models.Model):
author = models.ForeignKey(User, on_delete=models.CASCADE)
timestamp = models.DateTimeField(auto_now_add=True)
content = models.TextField()
group = models.ForeignKey(Group, on_delete=models.CASCADE)
def __str__(self) -> str:
date = self.timestamp.date()
time = self.timestamp.time()
return f"{self.author}:- {self.content} @{date} {time.hour}:{time.minute}"
Модель события
Мы будем отслеживать приходящих и уходящих пользователей с помощью данной модели событий.
Модель, которая хранит все события, связанные с группой, например, когда пользователь присоединяется к группе или покидает ее:
class Event(models.Model):
CHOICES = [
("Join", "join"),
("Left", "left")
]
type = models.CharField(choices=CHOICES, max_length=10)
description= models.CharField(help_text="A description of the event that occurred",\
max_length=50, editable=False)
user = models.ForeignKey(User, on_delete=models.CASCADE)
timestamp = models.DateTimeField(auto_now_add=True)
group = models.ForeignKey(Group ,on_delete=models.CASCADE)
def save(self, *args, **kwargs):
self.description = f"{self.user} {self.type} the {self.group.name} group"
super().save(*args, **kwargs)
def __str__(self) -> str:
return f"{self.description}"
Миграции
Следующим шагом будет запуск миграции для только что созданных вами моделей:
python manage.py makemigrations chat
python manage.py migrate
Мы видим что наши таблицы успешно создались:
Включите три модели в файл admin.py, чтобы иметь к ним доступ на странице администратора:
from .models import *
# Register your models here.
admin.site.register(Message)
admin.site.register(Event)
admin.site.register(Group)