I want to model the database table of a django channels private chat in the most effective way possible so that retrieving the messages would not take a lot of time.
For that I have create a one to one room since every two users should have their unique room.
And I created a separate message table with a foreign key relation with the (oneToOneRoom) table.But what bothers me is that since the sender and the receiver of the message can only be one of the two users of the room I do not want set (sender and receiver) as foreign Key to the users table. Can I have a better implementation of that. Or is their any other way of modeling those tables. Any help would be highly appreciated.
Here is the models.py file.
class singleOneToOneRoom(models.Model):
first_user = models.ForeignKey(
User, on_delete=models.SET_NULL, related_name="first_user", blank=True, null=True)
second_user = models.ForeignKey(
User, on_delete=models.SET_NULL, related_name="second_user", blank=True, null=True)
room_name = models.CharField(max_length=200, blank=True, unique=True)
def __str__(self):
return f"{self.first_user}-{self.second_user}-room"
class Meta:
unique_together = ["first_user", "second_user"]
class messages(models.Model):
room = models.ForeignKey(
singleOneToOneRoom, on_delete=models.CASCADE, related_name="messages")
message_body = models.TextField()
sender = models.ForeignKey(
User, on_delete=models.CASCADE, related_name="msg_sender")
receiver = models.ForeignKey(
User, on_delete=models.CASCADE, related_name="msg_receiver")
date_sent = models.DateTimeField(auto_now_add=True)
def __str__(self):
return f"{self.sender}_to_{self.receiver}"
>Solution :
The design seems ok. You can add more constraints to be sure, that message belongs to the right users.
Here my suggestions:
- Make
first_userandsecond_userNOT NULLfields. - Make sure, that you have exactly 1 room for users pair (first_user.id < second_user.id)
- Make sure, that (receiver, sender) pair equals (first_user, second_user) pair
class singleOneToOneRoom(models.Model):
first_user = models.ForeignKey(
User, on_delete=models.CASCADE, related_name="first_user", null=False)
second_user = models.ForeignKey(
User, on_delete=models.CASCADE, related_name="second_user", null=False)
class Meta:
unique_together = ["first_user", "second_user"]
constraints = [
models.CheckConstraint(check=Q(first_user__id__lt=F('second_user__id')), name='unique_user_pair'),
]
class messages(models.Model):
room = models.ForeignKey(
singleOneToOneRoom, on_delete=models.CASCADE, related_name="messages")
message_body = models.TextField()
sender = models.ForeignKey(
User, on_delete=models.CASCADE, related_name="msg_sender")
receiver = models.ForeignKey(
User, on_delete=models.CASCADE, related_name="msg_receiver")
class Meta:
constraints = [
models.CheckConstraint(
check=Q(sender=F('singleonetooneroom__first_user') & Q(receiver=F('singleonetooneroom__second_user'))
| Q(sender=F('singleonetooneroom__second_user') & Q(receiver=F('singleonetooneroom__first_user')),
name='valid_sender_and_receiver'
),
]