Фильтр объектов из таблицы на основе поля ManyToMany
Я работаю над приложением для обмена сообщениями. Модели следующие.
class ChatRoom(SafeDeleteModel):
_safedelete_policy = SOFT_DELETE_CASCADE
room_name = models.CharField(max_length=100, null=True, blank=True)
participants = models.ManyToManyField(User)
class Meta:
db_table = TABLE_PREFIX + "chat_room"
class Message(SafeDeleteModel):
_safedelete_policy = SOFT_DELETE_CASCADE
chat_room = models.ForeignKey(ChatRoom, on_delete=models.CASCADE)
message = models.TextField()
sent_by = models.ForeignKey(User, on_delete=models.CASCADE)
created_on = models.DateTimeField(default=django.utils.timezone.now)
class Meta:
db_table = TABLE_PREFIX + "chat_message"
Мне нужно отфильтровать объект ChatRoom, который содержит список пользователей.
Eg: При отправке таких данных в api
{
"participants": [2,3]
}
Он должен вернуть объект ChatRoom, который содержит пользователя '2' и пользователя '3' в качестве участников.
Я пробовал фильтровать его с помощью
room = ChatRoom.objects.filter(participants__in=serializer.validated_data['participants'])
но возвращает список объектов комнаты с пользователем '1' и пользователем '2'.
Я также пробовал использовать get(), но он возвращает ошибку.
Что я делаю неправильно и как мне сделать это правильно?
Спасибо, что рассмотрели мою проблему. Надеюсь, у вас есть решение.
Вы сказали, что используете Query...
ChatRoom.objects.filter(participants__in=serializer.validated_data['participants'])
- filter функция возвращает список объектов модели, соответствующих условиям.
- get функция возвращает только один объект модели и если ни один или более одного элемента не соответствует условию, то возникает исключение. Поэтому get используется только для ключей-кандидатов или уникальных результирующих условий.
В вашем случае, я полагаю, оба участника могут быть частью многих комнат, также может быть возможность, что такой комнаты нет. Если вы хотите, чтобы возвращался только один набор запросов, вы можете использовать это.
room_list= ChatRoom.objects.filter(participants__in=serializer.validated_data['participants']
if len(room_list) >0:
room = room_list[0]
else:
room = None
Это вернет первую комнату, в которой присутствуют все заданные участники, вы можете заменить 0 на любое допустимое значение или добавить что-то еще в запрос, если вы хотите, чтобы он вернул конкретную комнату.