Фильтр набора запросов на основе совпадающего поля в другом наборе запросов, но ограниченный связанным полем в другом наборе запросов

Я пытаюсь создать фильтр на основе двух наборов запросов двух связанных моделей (обе уже ранее отфильтрованы). Первый возвращает список идентификаторов и концепций (имен) с соответствующими значениями (определениями).

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. Я удалил некоторые комментарии, а также название, но это не должно быть проблемой, если оно общедоступно.

Вернуться на верх