在外键表上运行聚合函数

时间:2017-02-02 22:51:23

标签: django django-models

models.py
class Contest(models.Model):
    sport = models.CharField(max_length=200)

class Player(models.Model):
    name = models.CharField(max_length=200)
    contest = models.ManyToManyField(Contest)

class Entry(models.Model):
    num_entries = models.IntegerField()
    player = models.ForeignKey('Player',on_delete=models.CASCADE)

如何查找基于运动的玩家,然后在条目表中的利润条目上运行聚合函数。这是我想采取的一种方法:

from .models import *
from django.db.models import Avg

player = Player.objects.filter(name='Player A').filter(contest__sport='nba').aggregate(Avg(entries__num_entries))

3 个答案:

答案 0 :(得分:0)

如果您想让玩家有多个条目,您的模型应如下所示:

from django.db import models


class Contest(models.Model):
    sport = models.CharField(max_length=200)

class Player(models.Model):
    name = models.CharField(max_length=200)
    contests = models.ManyToManyField(Contest)

class Entry(models.Model):
    # some entry fields

    # every entry has one player connected, so every player can have multiple entries (One to N). The reverse field of the player will be called "entries"
    player = models.ForeignKey('Player',on_delete=models.CASCADE, related_name='entries')

然后你可以计算这样一个球员的参赛人数:

from .models import Player
from django.db.models import Count

aggregate = Player.objects.filter(name='Player A', contests__sport__in=['nba']).aggregate(num_entries=Count(entries))
print(aggregate['num_entries'])

或者更简单,你可以这样做:

from .models import Entry

num_entries = Entry.objects.filter(player__name='Player A', player__contests__sport__in=['nba']).count()

答案 1 :(得分:0)

由于ORM的工作原理,您可能需要反转查询:

player = Player.objects.aggregate(Avg(entries__num_entries)).filter(name='Player A').filter(contest__sport='nba')

而不是:

Player.objects.filter(name='Player A').filter(contest__sport='nba').aggregate(Avg(entries__num_entries))

在前者中你的查询基本上是“按NBA过滤,然后汇总”,而后者则说“聚合,然后过滤”

答案 2 :(得分:0)

解决方案是:

Player.objects.filter(name='Player A').filter(contest__sport='nba').aggregate(Avg('entry__num_entries'))