Django - Группировка по одному столбцу (с использованием количества) - PullRequest
0 голосов
/ 17 июня 2019

Я бы хотел получить такой эффект

SELECT "restApi_comment"."id", "restApi_comment"."text", "restApi_comment"."movie_id", COUNT("restApi_comment"."id") AS "count" FROM "restApi_comment" GROUP BY  "restApi_comment"."movie_id" ORDER BY "count" DESC

, но Django основан на этом

obj = Comment.objects.annotate(count=Count('movie_id')).order_by('-count')

дай мне

SELECT "restApi_comment"."id", "restApi_comment"."text", "restApi_comment"."movie_id", COUNT("restApi_comment"."id") AS "count" FROM "restApi_comment" GROUP BY "restApi_comment"."id", "restApi_comment"."text", "restApi_comment"."movie_id" ORDER BY "count" DESC

проблема заключается в группировке, основанной не на одном столбце (movie_id), а на трех (id, text, movie_id).

[models.py]

class Comment(models.Model):
    text = models.CharField(max_length=50, blank=True)
    movie = models.ForeignKey(Movie, on_delete=models.CASCADE)

Я попробовал этот метод

obj=Comment.objects.values('movie_id').annotate(count=Count('movie_id')).order_by('-count').values('movie_id', 'text')

, который дал мне такой эффект и не вернул все столбцы

SELECT "restApi_comment"."movie_id", COUNT("restApi_comment"."movie_id") AS "count" FROM "restApi_comment" GROUP BY "restApi_comment"."movie_id" ORDER BY "count" DESC

Ответы [ 2 ]

0 голосов
/ 17 июня 2019

Я использовал это models.py для тестирования на основе того, что вы запрашиваете.

from django.db import models


class Movie(models.Model):
    title = models.TextField()

    def __str__(self):
        return self.title


class Comment(models.Model):
    movie = models.ForeignKey(
        Movie, 
        related_name='comments',
        on_delete=models.CASCADE,
    )
    text = models.TextField()

В то время как количество комментариев кажется вам наиболее интересным, вы получите список Movie объекты, помеченные (и упорядоченные) количеством их комментариев, означают, начиная с модели Movie, например, (взято из документа Django для агрегации ):

Movie.objects.annotate(count=Count('comments')).order_by('-count')

Частичный вывод изконтрольный пример, чтобы показать население и результаты:

>>> from django.db.models import Count
>>> from movies.models import Movie, Comment
>>> 
>>> for title, comment_count in (
...     ('The Meg', 32), 
...     ('Citizen Kane', 126), 
...     ('Meet the Feebles', 1),
...     ('Dellamorte Dellamore', 900),
... ):
...     m = Movie(title=title)
...     m.save()
...     for i in range(comment_count):
...         Comment(movie=m, text=i).save()
... 
>>> for m in Movie.objects.annotate(count=Count('comments')).order_by('-count'):
...     print(m, m.count)
... 
Dellamorte Dellamore 900
Citizen Kane 126
The Meg 32
Meet the Feebles 1
0 голосов
/ 17 июня 2019
results = []
movies = Movie.objects.distinct()
for movie in movies:
    results.append('name': movie.name, 'total_comments':Comment.objects.filter(movie=movie).count()) 

results - это список словарей, содержащих два значения, одно из которых является ключевым name и используется для дифференциации ваших результатов. Второе значение - ключ total_comments, и это подсчет количества комментариев к фильму, который был запрошен с помощью .filter()

.

чтобы вы могли в шаблоне сделать:

{% for movie in movies %}
    # some layout html with your data in it
{% endfor %}

Надеюсь, это поможет:)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...