Использование фильтра в запросе с 2 полями ManyToMany в Django

#django #filter #many-to-many #field

#django #Фильтр #многие ко многим #поле

Вопрос:

Я постараюсь изо всех сил описать, что я пытаюсь здесь сделать. У меня есть 3 класса:

  • Вопрос
  • Тип вопроса
  • QuestionTemplate

И отношения являются:

  • Вопрос <-ManyToMany-> questionType
  • QuestionTemplate <-ManyToMany-> questionType

Итак, запрос находится в методе внутри QuestionTemplate, который выдает мне список возможных вопросов с тем же типом questionType, которые связаны с QuestionTemplate.

Я пробовал: questions = Question.objects.filter(type__in = template.type.all()) Где «template» — это объект QuestionTemplate. Но этот запрос возвращает мне вопросы, у которых есть хотя бы один questionType внутри списка questionType из шаблона. Что я хочу сделать, так это получить точно такие же типы вопросов как в вопросе, так и в шаблоне.

Я много чего перепробовал, но не могу заставить это работать, пожалуйста, кто-нибудь, спасите меня!

Комментарии:

1. пожалуйста, уточните, что вы пытаетесь получить. Вы пытаетесь получить вопросы, которые в точности совпадают в …? Я думаю, вы пропустили пару слов из своего первоначального сообщения.

2. Я хочу получить вопросы, которые имеют одинаковые (точно) связи с questionType в заданном QuestionTemplate. Итак, если я получу шаблон, содержащий questionType = (Type1, Type2 и Type3) Запрос вернул бы все вопросы, которые имеют связи с questionType = (Type1, Type2, Type3). Таким образом, любой другой вопрос, который имеет другую связь с questionType, например (Type1, Type2 и Type5), не войдет в список.. То же самое относится к одному вопросу, который имеет QuestionTypes = (Type1 и Type2), поскольку в нем нет Type3, подобного шаблону, он также будет удален.

Ответ №1:

 types = template.type.all()
query = Question.objects
for t in types:
    query = query.filter(type = t)
questions = []
for q in query.select_related('type'):
    ok = True
    for t in q.type.all():
        if t not in types:
            ok = False
            break
    if ok:
        questions.append(q)
save_questions_in_m2m_relations_so_that_you_dont_have_to_repeat_this(questions)
  

Довольно неуклюжий, но должен делать то, что вам нужно.

Комментарии:

1. Говоря о производительности, лучше ли это делать только с помощью filter / exclude вместо итерации по списку, проверяя, какое из них в порядке?

2. @Arruda: Filter /exclude выполняет все вычисления в базе данных, так что это всегда быстрее, часто в десять раз. Но я не мог придумать решение в чистом filter / exclude. Возможно, вы могли бы сделать это в raw SQL. Но прежде чем проводить оптимизацию , убедитесь, что это на самом деле узкое место в производительности. Может сэкономить вам много времени, если это не так.

3. Основная причина, по которой я хочу это знать, заключается в том, что я хочу научиться решать подобную проблему … это решение хорошо подошло бы к проблеме, с которой я сталкиваюсь сейчас, но, возможно, в будущем я столкнусь с другой проблемой, которая может быть решена только с помощью запросов, поэтому я хотел знать, как это сделать таким образом.