И условный запрос Django с использованием одного и того же ключевого слова

У меня есть приложение Django с моделью публикации и моделью тега. Каждая публикация имеет один или несколько тегов, связанных с ней. Я хочу запросить базу данных с набором из двух тегов и вернуть только публикации, которые имеют ОБА из этих тегов.

Кажется, я не могу найти синтаксис для этого, хотя я уверен, что он легко доступен - я полагаю, что я не использую правильный язык для поиска. То, что я уже пробовал, это:

pubs_for_tags = Publication.objects.filter(tags__title__istartswith=q, tags__title__istartswith=q2)

Но это дает мне ошибку «повторяется аргумент ключевого слова». Я также пробовал некоторые варианты этого, но пока ничего не сработало. Может ли кто-нибудь просветить меня о правильном синтаксисе для этого?


person jac300    schedule 31.05.2013    source источник


Ответы (3)


Я знаю, что это старо, но я только что столкнулся с той же проблемой и понял, что она указывает на (насколько мне известно) недокументированный аспект использования фильтров Django в отношениях «один ко многим» или «многие ко многим». Два условия, заданные в одном фильтре, применяются к одному и тому же связанному объекту. Два условия, заданные в отдельных фильтрах, могут соответствовать двум отдельным связанным объектам.

Другой способ думать об этом состоит в том, что каждый полный фильтр просматривает только один связанный объект за раз, удаляя результат, если все его связанные объекты не соответствуют этому фильтру. Учитывая это, крайне редко вам понадобятся два условия в одном фильтре с использованием одного и того же ключевого слова.

Рассмотрим следующий запрос:

pubs_for_tags = Publication.objects.filter(
    tags__title__istartswith=q,
    tags__title__iendswith=q2
    )

vs

pubs_for_tags = Publication.objects.filter(
    tags__title__istartswith=q,
    ).filter(
    tags__title__iendswith=q2
    )

Первый запрос находит публикации, каждая из которых имеет один тег, который оба начинаются с q и заканчиваются на q2. Когда ключевое слово совпадает (обратите внимание, что в моем примере я использовал два разных ключевых слова), вы также получаете ошибку «повторяющийся аргумент ключевого слова».

Второй запрос находит публикации, у каждой из которых есть тег, начинающийся с q, и тег, оканчивающийся на q2, но это могут быть два разных тега для каждой публикации. Судя по вашему сообщению, это очень близко к тому, что вам нужно (просто измените «iendswith» на «istartswith»). Единственная часть, которая может сломаться, — это если q и q2 совпадают или одна из них является подстрокой другой. В этом случае публикация может иметь один тег, удовлетворяющий обоим условиям.

Обратите внимание, что все это означает, что использование объектов Q (которые nnmware и Gaurav дали в качестве возможного решения) не даст вам желаемого результата. Наличие двух объектов Q в одном фильтре приводит к тому же поведению, что и в первом примере, но позволяет обойти ошибку «повторяющийся аргумент ключевого слова».

pubs_for_tags = Publication.objects.filter(
    Q(tags__title__istartswith=q) & Q(tags__title__istartswith=q2)
    )
person Jonathan Richards    schedule 14.04.2016

попробуй это

from django.db.models import Q
pubs_for_tags = Publication.objects.filter(Q(tags__title__istartswith=q) & Q( tags__title__istartswith=q2))

проверьте эту ссылку

person Wagh    schedule 24.07.2014

person    schedule
comment
одинаковы ли они по уровню эффективности. - person Shubham; 24.02.2016
comment
Эти два вызова ведут себя очень по-разному из-за того, как цепные фильтры работают со связанными объектами. Смотрите мой ответ для получения дополнительной информации. - person Jonathan Richards; 03.12.2019