Как получить "наименее частый" элемент в таблице путем фильтрации с помощью данных из другой таблицы
Я пытаюсь создать аудио базу данных, и вот некоторые из моделей, которые я использую:
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