DRF, вложенная через фильтрацию сериализации модели
Каждая из моих моделей наследуется от базовой модели, которая содержит поле publishing_status
, которое помогает мне контролировать, будет ли объект включен в возвращаемые данные.
class BaseModel(models.Model):
class PublishingStatus(models.TextChoices):
ACCEPTED = 'accepted', 'Accepted'
REJECTED = 'rejected', 'Rejected'
publishing_status = models.CharField(
max_length=9,
choices=PublishingStatus.choices,
default=PublishingStatus.DRAFT,
help_text="Publishing status represents the state of the object. By default it is 'draft'"
)
class Meta:
abstract = True
Вот две модели Word
и Homonym
они обе наследуют от BaseModel
:
class Word(BaseModel):
definition = models.CharField(max_length=255)
homonyms = models.ManyToManyField('self', through='Homonym', through_fields=('homonym', 'word'))
class Homonym(BaseModel):
homonym = models.ForeignKey(Word, on_delete=models.CASCADE)
word = models.ForeignKey(Word, on_delete=models.CASCADE)
Омонимы, по сути, тоже являются словами, поэтому здесь у меня есть самореференция, но через модель Homonym
, так что я могу контролировать эти отношения, чтобы они были публичными или нет для моего сайта.
Затем следуйте за сериализаторами и, вероятно, решение должно быть передано сюда:
class HomonymSerializer(serializers.ModelSerializer):
class Meta:
model = Homonym
fields = '__all__'
class WordSerializer(serializers.ModelSerializer):
homonyms = HomonymSerializer(many=True)
class Meta:
model = Word
fields = '__all__'
Вопрос: В настоящее время отображаются все омонимы, независимо от того, приняты они или нет. Как я могу ограничить вложенный сериализатор, чтобы он включал только омонимы с publishing_status="accepted"
?
Вот мое мнение:
class WordRetrieveView(RetrieveAPIView):
serializer_class = WordSerializer
queryset = Word.objects.all().filter(publishing_status='accepted')
Мое текущее решение состоит в том, чтобы определить поле homonyms
как SerializerMethodField()
и фильтровать набор запросов здесь (у меня есть ощущение, что это не лучший способ и не способ django):
class WordSerializer(serializers.ModelSerializer):
homonyms = serializers.SerializerMethodField()
class Meta:
model = Word
fields = '__all__'
@staticmethod
def get_homonyms(obj):
homonyms = Homonym.objects.all().filter(publishing_status='accepted', homonym_id=obj.id)
return [HomonymSerializer(Word.objects.get(id=h.homonym_id)).data for h in homonyms]
Ваш основной набор запросов будет влиять только на результаты, возвращаемые Word
, но не на связанные омонимы. Поэтому вам нужно применить тот же фильтр к связанным объектам, если вы хотите, чтобы возвращалось только определенное подмножество.
В этом случае достаточно просто изменить ваш набор запросов на:
Word.objects.filter(publishing_status='accepted').prefetch_related(
Prefetch('homonyms', queryset=Homonym.objects.filter(publishing_status='accepted'))
)
Это позволит получить все Word
, которые приняты, а также получить любые связанные омонимы на слово, которые также приняты.