Расширенная фильтрация Django для набора запросов, который может иметь много связанных внешних ключей
Я пытаюсь отсортировать запрос в django на модели, которая может иметь несколько внешних ключей. Я хочу, чтобы фильтрация применялась только к одному из этих ключей, и мне очень трудно заставить это работать.
models.py
class Post(models.Model):
content = models.TextField(max_length=1000)
reaction_counts = GenericRelation(ReactionCount, related_query_name='post_reaction_counts')
class ReactionType(models.TextChoices):
LIKE = 'like', ('Like')
DISLIKE = 'dislike', ('Dislike')
STAR = 'star', ('Star')
LOVE = 'love', ('Love')
LAUGH = 'laugh', ('Laugh')
class ReactionCount(models.Model):
count = models.PositiveIntegerField(default=0)
type = models.CharField(
max_length=7,
choices=ReactionType.choices,
)
post = models.ForeignKey(Post, related_name="reaction_count", on_delete=models.CASCADE)
В приведенном выше примере ключевым элементом (Foreign Key Relation) является ReactionCount для Post. Я хочу отсортировать посты по постам с наибольшим количеством лайков, дислайков, звезд, любви, смеха и т.д.
Я пытаюсь сделать это, выполняя Post.objects.all().order_by('-reaction_count__type', '-reaction_count__count')
Однако это не работает, так как существует несколько объектов ReactionCount для каждого поста, что приводит к тому, что упорядочивание не работает.
Мне нужен способ указать, что я хочу, чтобы упорядочивание подсчета применялось только к сообщениям с внешним ключом ReactionCount определенного типа.
Есть ли способ сделать это, изменив способ упорядочивания в объекте Posts? Если нет, есть ли способ изменить мои модели, сохранив при этом поле выбора ReactionType, чтобы можно было упорядочивать по количеству определенного типа реакции?
В качестве примечания, мне удалось заставить это работать, запрашивая объекты ReactionCount напрямую, однако если вы удалите фильтрацию по определенному типу, вы получите дублирующиеся результаты постов, поскольку один пост может иметь несколько типов реакции, поэтому я считаю, что этот вариант не будет работать, однако я открыт для предложений!
Я не уверен, что понимаю, какой порядок вам нужен, поэтому вот несколько примеров.
Вы хотите получить посты с наибольшим количеством лайков
Post.objects.filter(reaction_count__type=ReactionCount.ReactionType.LIKE.value).order_by("-reaction_count__count")
Если вам нужен пост с наибольшим количеством реакций
Post.objects.alias(reaction_total=Sum("reaction_count__count")).order_by("-reaction_total")
Если вам нужен пост с наибольшим количеством положительных реакций
Post.objects.alias(positive_reactions=Sum("reaction_count__count", filter=Q(reaction_count__type__in=[ReactionCount.ReactionType.LIKE.value, ReactionCount.ReactionType.LOVE.value ...]))).order_by("-positive_reactions")