Это не будет переводиться в один и тот же запрос SQL, но даст те же результаты, используя внутренний запрос.
inner_query = Label.objects.annotate(article_label=OuterRef('label')).filter(article_label__icontains=F('name'))
articles = Article.objects.annotate(labels=Subquery(inner_query.values('name')[:1])).filter(labels__isnull=False)
Это должно примерно соответствовать следующему:
select a.* from myapp_article a where exists (select l.* from myapp_label l where a.label ilike '%' || l.name || '%')
Но из-за текущей проблемы в Django относительно использования OuterRef в аннотациях этот подход не 'т работа.Нам нужно использовать обходной путь, предложенный здесь , до тех пор, пока проблема не будет решена, чтобы этот запрос работал, например:
Сначала определите пользовательское выражение
class RawCol(Expression):
def __init__(self, model, field_name):
field = model._meta.get_field(field_name)
self.table = model._meta.db_table
self.column = field.column
super().__init__(output_field=CharField())
def as_sql(self, compiler, connection):
sql = f'"{self.table}"."{self.column}"'
return sql, []
Затем выполните сборкуВаш запрос, используя это выражение
articles = Article.objects.all().annotate(
labels=Subquery(
Label.objects.all().annotate(
article_label=RawCol(Article, 'label')
).filter(article_label__icontains=F('name')).values('name')[:1]
)
).filter(labels__isnull=False)
Это должно вернуть экземпляры модели Article, чье поле метки содержит значение из поля имени модели Label