Как получить "наименее частый" элемент в таблице путем фильтрации с помощью данных из другой таблицы

Я пытаюсь создать аудио базу данных, и вот некоторые из моделей, которые я использую:

class State(models.Model):
    abbreviation = models.CharField(max_length=2)
    ...

class City(models.Model):
    state = models.ForeignKey(State, on_delete=models.CASCADE)
    ...

class Sentence(models.Model):
    text = models.CharField(max_length=255)
    ...

class Speaker(models.Model):
    birth_city = models.ForeignKey(
        City, on_delete=models.CASCADE, related_name="birth_city"
    )
    ...

class Record(models.Model):
    sentence = models.ForeignKey(Sentence, on_delete=models.CASCADE)
    speaker = models.ForeignKey(Speaker, on_delete=models.CASCADE)
    ...

и я пытаюсь настроить ViewSet, чтобы получить конечную точку, такую как /sentence/?state=STATE, где STATE - это State.abbreviation, которая вернет мне наименьшее записанное предложение для этого состояния.

Вот что у меня есть на данный момент:

class SentenceViewSet(viewsets.ModelViewSet):
    serializer_class = SentenceSerializer
    permission_classes = (permissions.IsAuthenticatedOrReadOnly,)

    def get_queryset(self):
        queryset = Sentence.objects.all()
        state = self.request.query_params.get("state", None)
        if state is not None:
            # Get all records for this state
            records = Record.objects.filter(
                speaker__birth_city__state__abbreviation=state
            )
            # Get sentence with the lowest number of records
            queryset = queryset.filter(
                id=records.values("sentence")
                .annotate(dcount=Count("id"))
                .order_by("dcount")[0]["sentence"]
            )
        else:
            queryset = queryset.order_by("text")
        return queryset

К сожалению, это вернет только те предложения, которые я уже записал. Как мне обойти это?

Я разобрался! Для тех, кому интересно, это работает:

class SentenceViewSet(viewsets.ModelViewSet):
    serializer_class = SentenceSerializer
    permission_classes = (permissions.IsAuthenticatedOrReadOnly,)

    def get_queryset(self):
        queryset = Sentence.objects.all()
        state = self.request.query_params.get("state", None)
        if state is not None:
            # Get sentence with the lowest number of records
            sentence = (
                queryset.annotate(num_records=Count("record"))
                .order_by("num_records")
                .first()
            )
            queryset = queryset.filter(id=sentence.id)
        else:
            queryset = queryset.order_by("text")
        return queryset
Вернуться на верх