Набор запросов только по первому внешнему ключу, связанному с экземпляром
Допустим, например, у меня есть такие модели:
class Person(models.Model):
name = models.CharField(max_length=50, blank=True, null=True, verbose_name=_('name'))
class Keyword(models.Model):
value = models.CharField(max_length=50, blank=True, null=True, verbose_name=_('name'))
person = models.ForeignKey('Keyword', on_delete=models.CASCADE)
Я хотел бы сделать запрос по модели Person, где мы фильтруем ТОЛЬКО по первому ключевому слову, связанному с этим человеком.
Список ключевых слов всегда упорядочен.
Так, например:
У человека Джон Доу есть 3 ключевых слова (Программирование, Путешествия, Семья)
Я бы хотел сделать что-то вроде этого (если это возможно)
Person.objects.filter(keyword_"first"="Programming")
You can annotate with .alias(…) [Django-doc] with a Subquery expression [Django-doc], and then filter:
from django.db.models import OuterRef, Subquery
class Person.objects.alias(
first_keyword=Subquery(
Keyword.objects.filter(
person=OuterRef('pk')
).values('value')[:1]
)
).filter(
first_keyword='Programming'
)
But models are by default unordered: that means that each time a different keyword can be the first. Only if you have a column and an ordering option [Django-doc], or an .order_by(…) clause [Django-doc] in the subquery, it is guaranteed that a certain item will be the first keyword.
Вы можете сделать фильтрацию необязательной с помощью поля only_first, которое будет фильтровать по первому элементу, если True и по всем элементам, если False:
from django.db.models import OuterRef, Q, Subquery
class Person.objects.alias(
first_keyword=Subquery(
Keyword.objects.filter(
person=OuterRef('pk')
).values('value')[:1]
)
).filter(
Q(first_keyword='Programming') |
Q(only_first=False, keyword__value='Programming')
)