Ved-форум поддержки
Программирование => Django => Тема начата: DigitalMag от Мая 25, 2019, 05:33:57 pm
-
Есть модель:
class Dialogue(models.Model):
Partakers = models.ManyToManyField(Profile, related_name='partakers')
Пытаюсь сделать выборку по Partakers
dialog = Dialogue.objects.get_or_create(Partakers=[recipient_id,self.request.user.id])
Но получаю
TypeError: int() argument must be a string or a number, not 'list'
-
Пробовал
dialog = Dialogue.objects.get(partakers__in=[recipient, self.request.user])
Получаю can not resolve partakers into fields
-
Можешь сделать так:
dialog = Dialogue.objects.filter(Partakers__id=recipient_id).get(Partakers=self.request.user)
Вернет все беседы, где есть эти собеседники
-
Спасибо.
Но мне нужно не просто все беседы, где есть эти собеседники, а беседу, в которой есть ТОЛЬКО эти собеседники.
Пробовал даже через Q-objects:
dialog = Dialogue.objects.filter(Q(Partakers__id=recipient_id), Q(Partakers__id=self.request.user.id))
пробовал отталкиваться от конкретного юзера:
dialog = self.request.user.dialogs.filter(Partakers=recipient)
Но получаю пустой кверисет
Запрос формируется такой:
SELECT ••• FROM "main_dialogue" INNER JOIN "main_dialogue_Partakers" ON ("main_dialogue"."id" = "main_dialogue_Partakers"."dialogue_id") WHERE ("main_dialogue_Partakers"."profile_id" = '20' AND "main_dialogue_Partakers"."profile_id" = '7') LIMIT 21
-
Этот запрос пытается одновременно найти в таблицы запись у которой profile_id=7 и одновременно 20,что невозможно.
Короче, какой вариант могу предложить
partakers = chain(Profile.objects.none(),[Profile.objects.get(id=buddy_id),self.request.user])
dialogs = Dialogue.objects.filter(Partakers__in=partakers).annotate(num_partekers=Count('Partakers'))
dialogs = [dialog for dialog in dialogs if dialog.num_partekers == 2]
print dialogs
По идее должно получиться как раз то, что вы хотите
Или попробуйте подобный фокус провернуть с запросом из моего предыдущего ответа: то есть выбрать диалог с количеством собеседников = 2.
Конечно, не самый красивый запрос, но то, что нужно
-
Спасибо
Переделал на
Dialogue.objects.filter(Partakers__id__in=[buddy_id,self.request.user.id])
-
У меня тут возник вопрос на засыпку. Что делает этот запрос?
dialogs = Dialogue.objects.filter(Partakers__in__id=[buddy_id,self.request.user.id])
dialogs = dialogs .annotate(num_partekers=Count('Partakers'))
dialogs = [dialog for dialog in dialogs if dialog.num_partekers == 2]
-
Выбирает все элементы, содержащие buddy_id и self.request.user.id. Во второй строке считает количество участников в элементе с id из этого списка. То есть те, где будет два - это наши клиенты
-
А если будет несколько диалогов с ними, все они попадут в выборку?
-
Хм. Да. Попробуйте тогда такой вариант:
dialogs = Dialogue.objects.filter(Partakers__id=recipient_id).filter(Partakers__id=sender_id)
dialogs = dialogs.annotate(num_partekers=Count('Partakers'))
dialogs = [dialog for dialog in dialogs if dialog.num_partekers == 2]
dialog = dialogs.pop()
-
Хм. Да. Попробуйте тогда такой вариант:
Пустоту возвращает. Он, видимо, ищет, чтобы recipient_id и sender_id были в одной строке