Первое решение, о котором я могу подумать, - это использование Условное выражение для добавления текста категории в SearchVector :
from django.db.models import Case, CharField, Value, When
from django.contrib.postgres.search import SearchVector
Art.objects.annotate(
category_text=Case(
When(category=1, then=Value('Digital Art')),
When(category=2, then=Value('Multimedia')),
default=Value(''),
output_field=CharField()
),
search=SearchVector('title') + SearchVector('category_text')
).filter(
search='Some Book Digital Art'
).values_list('title', flat=True)
Результатом этого запроса будетпохож на:
<QuerySet ['Some Book']>
И SQL, сгенерированный для PostgreSQL, выглядит так:
SELECT "arts_art"."title"
FROM "arts_art"
WHERE (
to_tsvector(COALESCE("arts_art"."title", '')) ||
to_tsvector(COALESCE(
CASE
WHEN ("arts_art"."category" = 1) THEN 'Digital Art'
WHEN ("arts_art"."category" = 2) THEN 'Multimedia'
ELSE ''
END, '')
)
) @@ (plainto_tsquery('Some Book Digital Art')) = TRUE
Обновление
Вы можете автоматически построить свой запрос из списка вариантов:
from django.db.models import Case, CharField, Value, When
from django.contrib.postgres.search import SearchVector
CATEGORIES = (
(1, 'Digital Art'),
(2, 'Multimedia'),
)
Art.objects.annotate(
category_text=Case(
*[When(category=c, then=Value(v)) for c, v in CATEGORIES],
default=Value(''),
output_field=CharField()
),
search=SearchVector('title') + SearchVector('category_text')
).filter(
search='Some Book Digital Art'
).values_list('title', flat=True)