Доброго времени суток, товарищи! Тут недавно столкнулся с django-channels. Хотел написать некий чат user2user, с возможностью на расширение (user2users или groupchat). Додумался только на 3 варианта:
1) Создать отдельно модели
models.py
class Message(models.Model):
user_from = models.ForeignKey(User, related_name="user_from")
user_to = models.ForeignKey(User, related_name="user_to")
created = models.DateTimeField(default=datetime.now())
message = models.TextField(blank=False)
delivered = models.DateTimeField(null=True, blank=True)
viewed = models.DateTimeField(null=True, blank=True)
deleted_out = models.DateTimeField(null=True, blank=True)
deleted_in = models.DateTimeField(null=True, blank=True)
size = models.FloatField(default=1.0)
class GroupMessage(models.Model):
group = models.ForeignKey(Group, related_name="groupchat")
user_from = models.ForeignKey(User, related_name="user_from")
user_to = models.ForeignKey(User, related_name="user_to")
created = models.DateTimeField(default=datetime.now())
message = models.TextField(blank=False)
delivered = models.DateTimeField(null=True, blank=True)
viewed = models.DateTimeField(null=True, blank=True)
deleted_out = models.DateTimeField(null=True, blank=True)
deleted_in = models.DateTimeField(null=True, blank=True)
size = models.FloatField(default=1.0)
Подключаться через websocket на канал, создавать общий Group("chat"). Проверять если пользователь общается с другим пользователем, то отдавать сериализированные данные. У клиента слушать эту группу и рендрить данные прям от сокета. Но тут проблема в том, что в одной единой группе создается каша, и при каждом изменении стейта приходится делать лишние проверки.
2) Все то же самое, но каким то умным образом создавать Group для конкретных пользователей. Не знаю может как нибудь брать генерировать уникальный hash от username-ов пользователей. И заставить конкретных пользователей слушать этот канал. Но в таком случае, есть риск утечки данных.
3) Создать единую модель Message, в которой оставить аттрибут Room "null"(У меня неприязнь к null-ам), Создавать Group() основываясь на этом Room. Но как потом отличить группу от простого диалога? Добавить еще одно поле типа в Room? И как реализовать работу channels правильно? Прошу помочь))
Ах да, вот код consumers.py с Группой 'chat'. Все работает, только это получился обший чат, пока без сохранений, позже после нормальной архитектуры, буду создавать инстансы Message
class UserSerializer(serializers.Serializer):
id = serializers.IntegerField()
username = serializers.CharField(max_length=100)
first_name = serializers.CharField(max_length=100)
last_name = serializers.CharField(max_length=100)
class Payload(object):
def __init__(self, j):
self.__dict__ = json.loads(j)
def ws_connect(message):
message.reply_channel.send({"accept": True})
Group('chat').add(message.reply_channel)
def ws_message(message):
token = jwt_response_payload_handler(Payload(message.content["text"]).token)
user = VerifyJSONWebTokenSerializer().validate(token)["user"]
Group('chat').send({'text': json.dumps({'message': Payload(message.content["text"]).message,
'sender': UserSerializer(user).data})})
def ws_disconnect(message):
Group('chat').discard(message.reply_channel)