Фильтрация моделей на основе конкатенации поля по отношению «один ко многим» в django - PullRequest
0 голосов
/ 06 февраля 2020

Скажем, у меня есть некоторые модели, определенные следующим образом:

Class Document(models.Model):
    pass

Class Paragraph(models.Model):
    text = models.CharField(max_length=2000)
    document = models.ForeignKey(Document, related_name="paragraphs")

И я хотел найти все Документы со словом "foo", содержащиеся в любом из текстовых полей их абзацев.

Что-то вроде:

Document.objects.annotate(text=[Concatenation of all paragraphs text]).filter(text__icontains='foo')

Как бы я go об этом Django, без написания прямых SQL запросов.

Ответы [ 3 ]

0 голосов
/ 06 февраля 2020

Как пишет @ReinstateMonica в своем ответе, начиная с фильтрации объектов Paragraph, это кажется самым простым подходом. Результат этого может быть использован для фильтрации документов. Если у вас есть только одно соответствующее текстовое поле, подход может выглядеть примерно так:

results = Document.objects.filter(
    pk__in=Paragraph.objects.filter(
        text__icontains='foo').values_list('document', flat=True)
    )

Если ваша модель Paragraph содержит несколько текстовых полей, вы можете сначала объединить поля, а затем использовать тот же подход, поэтому:

from django.db.models import Concat

qs = Document.objects.filter(
    pk__in=Paragraph.objects.annotate(
        conc_text=Concat('text', 'text2') # all relevant text fields
    ).filter(
        conc_text__icontains='foo'
    ).values_list(
        'document', flat=True
    )
)
0 голосов
/ 06 февраля 2020

ORM Django может выполнять запросов, которые охватывают отношения :

Document.objects.filter(paragraphs__text__icontains='foo')
0 голосов
/ 06 февраля 2020

Как насчет этого:

queryset = Paragraph.objects.filter(text__icontains='foo')

text = ''.join(obj.text for obj in queryset)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...