Фильтр набора запросов на основе совпадающего поля в другом наборе запросов, но ограниченный связанным полем в другом наборе запросов
Я пытаюсь создать фильтр на основе двух наборов запросов двух связанных моделей (обе уже ранее отфильтрованы). Первый возвращает список идентификаторов и концепций (имен) с соответствующими значениями (определениями).
dqs: ID + концепция + определения + ассоциированный язык (любой из четырех)
Например:
<QuerySet [<Definition: Definition (en) for #39: CBD, central business district: definition text>, <Definition: Definition (en) for #184: migration: definition text...>
Во втором также есть идентификаторы и понятия, которые могут иметь или не иметь совпадающие значения в первом списке.
tqs: ID1 + concept1 + terms (lang 1); ID1 + concept1 + terms (lang 2)... ID2 + concept1 + terms (lang 1) и т.д.
Например:
<QuerySet [<Translation: “other language term entry” (fr) for #1: abiotic component>, <Translation: “abiotic component” (en) for #1: abiotic component>, <Translation: “yet another language term entry” (es) for #1: abiotic component>...>
Идентификаторы и понятия (выраженные на английском языке, языке-источнике) не являются языковыми. Термины и определения являются языковыми. Таким образом, каждое понятие+идентификатор связано с терминами и определениями на четырех разных языках.
Мне нужно отфильтровать tqs так, чтобы он показывал только те записи, которые имеют совпадающие ID в dqs, и только на том языке, на котором был задан запрос на поиск определений (иначе он покажет все четыре записи, связанные с совпадающим ID).
Немного больше информации ниже.
Следующая часть def описывает, что происходит при поиске в глоссарии строки, соответствующей строке в определении (которая относится к определенной записи).
if data['definitions_show_partial_matches']:
if case_filter:
dqs = dqs.filter(text__contains=search_string)
else:
dqs = dqs.filter(text__icontains=search_string)
data['definitions_show_partial_matches'] - это форма BooleanField - пользователь указывает в чекбоксе, включает ли поиск также текст определения. case_filter указывает, должен ли поиск быть чувствительным к регистру.
Возможно появление более одного языка в dqs после фильтрации, если строка появляется в нескольких определениях, связанных с несколькими языками.
У меня есть импровизированное решение для сопоставления идентификаторов:
ids = []
for d in dqs:
ids.append(d.concept.id)
tqs = tqs.filter(concept__in=ids)
Однако, вероятно, это не очень эффективно. Я не знаю, как применить concept__in непосредственно в другом наборе запросов без предварительного извлечения идентификаторов в список. Я думал о перечислении в цикле for, но это, видимо, тоже не очень хорошая идея.
За всем этим следует код, который эффективно создает список результатов с усеченными определениями и максимальным количеством результатов.
dqs отображает только совпадающие определения. Поэтому мне нужно применить фильтр к tqs, чтобы записи, связанные с совпадающими идентификаторами, не отображались на всех четырех языках.
Мне также нужно встроить проверку, чтобы, если совпадение произошло на английском языке, мне нужно использовать поле "source_language" в связанной модели Глоссария, вместо "other_languages", и наоборот. Чтобы показать, как эти поля, а также поле концепции связаны с Глоссарием, и как я решил связанную проблему, вот код из шаблона ("current_language" является передаваемой переменной из представления):
{% with used_languages=concept.glossary.other_languages.all|dictsort:"iso_code" %}
{% if used_languages %}
<div class="language_link_list">
{% if current_language.name != "English" %}
<a href="{% url "concept_detail_for_language" pk=concept.pk lang=concept.glossary.source_language.pk %}" class="language_link">{{ concept.glossary.source_language.name }}</a>
{% endif %}
...
{% for lang in used_languages %}
{% if lang.pk != current_language.pk %}
<a href="{% url "concept_detail_for_language" pk=concept.pk lang=lang.pk %}" class="language_link">{{ lang.name }}</a>
{% endif %}
{% endfor %}
</div>
<br>
{% endif %}
{% endwith %}
Но это позволяет сверять значения с уже известным значением и применять его элемент за элементом, вместо одной команды фильтра, где моя проблема заключается в том, что значение может меняться в зависимости от позиции записи в другом наборе запросов и/или значения связанного поля в этом наборе запросов
Мне кажется, что это не должно быть сложно - я подумал о следующем:
- использование "update" - но есть не только одно значение для сравнения
- использование "annotate" - но определение уже имеет связанный язык, так что это не должно быть необходимо?
- использование Q() или выражений, связанных с prefetch_, как-то иначе?
Я прочитал много примеров, но почему-то ни один из них не связан с тем, что я пытаюсь сделать.
Спасибо!
EDIT: Вот соответствующие биты из соответствующих моделей. Это адаптация из онлайн-проекта под GNU GPL. Я удалил некоторые комментарии, а также название, но это не должно быть проблемой, если оно общедоступно.