Фильтрация обратного отношения "один ко многим" в Django
У меня есть модель с именем Item
и другая модель с именем ItemSynonym
с отношением один ко многим следующим образом:
from django.db import models
from django.conf import settings
from project.utils.models import UUIDModel
class Item(UUIDModel):
name = models.CharField(max_length=200)
class ItemSynonym(UUIDModel):
marker = models.ForeignKey(
Marker,
on_delete=models.CASCADE,
related_name="synonyms",
)
name = models.CharField(max_length=200)
Теперь я хочу добавить новое поле в модель ItemSynonym
под названием код языка, чтобы оно стало:
class ItemSynonym(UUIDModel):
marker = models.ForeignKey(
Marker,
on_delete=models.CASCADE,
related_name="synonyms",
)
language_code = models.CharField(
db_index=True,
max_length=8,
verbose_name="Language",
choices=settings.LANGUAGES,
default=settings.LANGUAGE_CODE,
)
name = models.CharField(max_length=200)
Как бы я ни хотел фильтровать, мне интересно, можно ли как-то фильтровать синонимы, изменяя только модели, чтобы мне не пришлось рыться во всей кодовой базе и фильтровать синонимы по отдельности, так что что-то вроде:
class Item(UUIDModel):
name = models.CharField(max_length=200)
synonyms = models.FilteredRelation(
"all_synonyms",
condition=models.Q(language_code=get_language()),
)
class ItemSynonym(UUIDModel):
marker = models.ForeignKey(
Marker,
on_delete=models.CASCADE,
related_name="all_synonyms",
)
language_code = models.CharField(
db_index=True,
max_length=8,
verbose_name="Language",
choices=settings.LANGUAGES,
default=settings.LANGUAGE_CODE,
)
name = models.CharField(max_length=200)
Хотя очевидно, что вышеописанное не работает, иначе бы меня здесь не было. Я также попробовал добавить аннотацию для FilteredRelation inside a custom manager for
Item`, но по какой-то причине аннотация даже не доступна как свойство.
Я довольно новичок в Django, но я уверен, что это не редкая проблема, поэтому я был бы также благодарен за любую информацию о том, каков идиоматический способ фильтрации таких отношений.
Да, вы можете фильтровать при предварительной выборке с помощью Prefetch
[Django-doc] объекта:
from django.db.models import Prefetch
items = Item.objects.prefetch_related(
Prefetch('all_synonyms', ItemSynonym.objects.filter(language_code='tr'))
)
например, если мы получим эти и перечислим их:
for item in items:
for synonym in item.all_synonyms.all():
print(synonym) # only Turkish ones
Таким образом, мы получим только турецкие