web-dev-qa-db-ja.com

Django複数の注釈のCount()

簡単なフォーラムモデルがあるとします。

class User(models.Model):
    username = models.CharField(max_length=25)
    ...

class Topic(models.Model):
    user = models.ForeignKey(User)
    ...

class Post(models.Model):
    user = models.ForeignKey(User)
    ...

ここで、ユーザーのサブセットの各ユーザーが持つトピックと投稿の数を確認したいとします(たとえば、ユーザー名が「ab」で始まる)。

したがって、投稿とトピックごとに1つのクエリを実行すると、

User.objects.filter(username_startswith="ab")
            .annotate(posts=Count('post'))
            .values_list("username","posts")

収量:

[('abe', 5),('abby', 12),...]

そして

User.objects.filter(username_startswith="ab")
            .annotate(topics=Count('topic'))
            .values_list("username","topics")

収量:

[('abe', 2),('abby', 6),...]

[〜#〜]ただし、[〜#〜]、両方に注釈を付けて1つのリストを取得しようとすると、奇妙な結果になります。

User.objects.filter(username_startswith="ab")
            .annotate(posts=Count('post'))
            .annotate(topics=Count('topic'))
            .values_list("username","posts", "topics")

収量:

[('abe', 10, 10),('abby', 72, 72),...]

トピックと投稿が一緒に乗算されるのはなぜですか?私はこれを期待しました:

[('abe', 5, 2),('abby', 12, 6),...]

正しいリストを取得する最良の方法は何でしょうか?

41
user749618

Count('topics', distinct=True) は正しいことをするべきだと思います。重複を避けるためにCOUNT(DISTINCT topic.id)ではなくCOUNT(topic.id)を使用します。

User.objects.filter(
    username_startswith="ab").annotate(
    posts=Count('post', distinct=True)).annotate(
    topics=Count('topic', distinct=True)).values_list(
    "username","posts", "topics")
100
fhahn

最後のクエリセットにdistinctを追加してみてください:

User.objects.filter(
    username_startswith="ab").annotate(
    posts=Count('post')).annotate(
    topics=Count('topic')).values_list(
    "username","posts", "topics").distinct()

詳細は https://docs.djangoproject.com/en/1.3/ref/models/querysets/#distinct を参照してください。ただし、注釈が複数のテーブルにまたがっているため、基本的に行が重複しています。

0
Jeremy Lewis