#django #python-2.7
#django #python-2.7
Вопрос:
У меня есть такая модель в Django
:
class VariantTag(models.Model):
saved_variants = models.ManyToManyField('SavedVariant')
Мне нужно получить все VariantTag
модели, у которых есть ManyToMany
поле saved_variants с точными идентификаторами, скажем (250, 251)
, не больше, не меньше. По характеру кода, с которым я имею дело, я не могу выполнить обратный поиск _set
. Итак, я ищу запрос (или несколько запросов дополнительная фильтрация кода python), который приведет меня туда, но таким образом:
query = Q(...)
tag_queryset = VariantTag.objects.filter(query)
Как этого можно достичь?
Я, вероятно, должен подчеркнуть: предоставленные сохраненные варианты (например (250, 251)
, должно быть AND
— ed, не OR
— ed.
Комментарии:
1. Почему релевантен обратный поиск? Ах, вы действительно хотите сделать это с другой стороны, но думаете, что не можете?
2. Idk, я могу просто ошибаться. Я хочу на самом деле фильтровать
saved_variants__in=
, как указано в ответе по внешним ключам и другим параметрам. Если я добавляю какие-либо дополнительные параметры вsaved_variants__in
запрос, это всегда ничего мне не дает.3. Допустим, у SavedVariant есть поле «name». Если вы хотите, чтобы все теги вариантов, которые сохранили варианты с полем имени, равным «Bob», вы делаете
VariantTag.objects.filter(saved_variants__name='Bob')
. Но, возможно, это не то, что вы ищете.
Ответ №1:
Используйте in
поиск
tag_queryset = VariantTag.objects.filter(saved_variants__in=[250,251])
Комментарии:
1. Можно ли добавить дополнительное свойство для фильтрации, например
VariantTag.objects.filter(name=..., saved_variants__in=[250,251])
?2. Да, это возможно
3. Так или иначе, не работает, пока я использую параметр модели внешнего ключа. Например.:
VariantTag.objects.filter(variant_tag_type__name='Name_of_the_tag', saved_variants__in=saved_variant_ids)
. Но я проверил DB, он есть.4. Я предполагаю, что это проблема дополнительного соединения, которое мне нужно сделать для получения дополнительных параметров. Возможно, будет задан новый вопрос. Это похоже на VariantTag -> VariantTagType . Последний содержит все параметры.
5. Я не думаю, что это дает
AND
операцию, но я думаю, что это такOR
, верно? Я решил проблему с моим внешним ключом, и теперь я вижу, что это решение, похоже, не работает: оно возвращает также модели, в которыхsaved_variants
есть только одно значение, например250
, но это не работает для меня, как указано в вопросе.
Ответ №2:
До сих пор я смог добиться AND
результата с помощью следующего кода:
tag_ids = VariantTag.objects.filter(variant_tag_type__name=tag_data['tag'],
saved_variants__in=saved_variant_ids).values_list('id', flat=True).distinct()
for tag_id in tag_ids:
saved_variants = list(VariantTag.objects.get(id=tag_id).saved_variants.all().values_list('id', flat=True))
if all(s in saved_variant_ids for s in saved_variants) and len(saved_variants) == len(saved_variant_ids):
return VariantTag.objects.get(id=tag_id)
Итак, я делаю следующее:
- Получение
OR
— результата - Перебор результирующих идентификаторов извлеченной модели и для каждого из них получение всех идентификаторов
ManyToMany
поля - Проверка, все ли полученные идентификаторы
ManyToMany
поля находятся в списке требуемых идентификаторов (saved_variant_ids
) - Если да — получить модель по идентификатору:
VariantTag.objects.get(id=tag_id)
В моем случае будет только одна такая модель с требуемыми идентификаторами в ManyToMany
поле. Если это не так для вас — просто добавьте идентификаторы модели (в моем случае tag_id
) в список — затем сделайте запрос для всех из них.
Если у кого-нибудь есть более краткий способ выполнения AND
ManyToMany
запроса код, было бы интересно посмотреть.