使用ORM聚合数据

时间:2011-02-13 03:55:45

标签: python django django-orm

Django / Python noob!

以下是我的模特:

class Match(models.Model):
    date = models.DateTimeField()
    court = models.ForeignKey(Court)
    players = models.ManyToManyField(User, through='Participant')

class Participant(models.Model):
    match = models.ForeignKey(Match)
    userid = models.ForeignKey(User)
    games_won = models.IntegerField()

class Court(models.Model):
    location_name = models.CharField(max_length=100)
    number = models.IntegerField()

我的观点目前是:

def index(request):
    matches_list = Participant.objects.all()
    return render_to_response('squash/base_matches.html', {'matches_list': matches_list}, context_instance = RequestContext(request))
    return HttpResponse(output)

我在数据库中的数据如下所示:

[match_id] [date]       [userid]  [games_won]  [court_location_name]  [court_number]
1          01-01-2011   mike      6            Queen                  5
1          01-01-2011   chris     4            Queen                  5
2          01-02-2011   bob       3            Queen                  6
2          01-02-2011   joe       4            Queen                  6
3          01-03-2011   jessie    5            Queen                  2
3          01-03-2011   john      5            Queen                  2

我希望能做的是:

[match_id] [date]       [player1] [player2]  [p1wins] [p2wins] [game_winner] [court_location_name]  [court_number]
1          01-01-2011   mike      chris      6        4        mike          Queen                  5
2          01-02-2011   bob       joe        3        4        joe           Queen                  6
3          01-03-2011   jessie    john       5        5        draw          Queen                  2  

这意味着我需要按match_id进行分组。我尝试在我的模板中执行类似下面的操作,但它只聚合match_id,日期和时间。我需要能够格式化其余的数据。在像之前那样的表格结构中。

{% regroup matches_list by match as matches_group %}
<ul>
{% for event in matches_group %}
    <li>{{ event.grouper }}
    <ul>
        {% for item in blah.list %}
        <li>{{ item.date }}</li>
        {% endfor %}
    </ul>
    </li>
{% endfor %}
</ul>

这里有什么建议吗?

更新:我使用matches_list = Participant.objects.values('match').annotate(total=Count('match'))进行了测试,我相信这就是让我聚合的原因。但是我不知道如何在模板中从中提取正确的字段。例如:

{% for matches in matches_list %}
<p>{{ matches.match.id }}</p>
{% endfor %}

这给了我3个条目(我可以看到3

),但没有打印出来。不确定我需要为{{ matches.match.id }}

做些什么

2 个答案:

答案 0 :(得分:1)

显示“数据库中的数据”的表格与您的模型不符,所以我有点困惑。

但按照您的模型,这里根本不需要聚合,因为您在Participant模型上直接有matches_won字段(我假设您需要显示的数据)。您可以通过迭代matches_list(为清晰起见省略格式)来执行此操作:

{% for match in matches_list %}
    {{ match.id }}
    {{ match.date }}
    {{ match.players.all.0.userid.username }}
    {{ match.players.all.1.userid.username }}
    {{ match.players.all.0.games_won }}
    {{ match.players.all.1.games_won }}
    {{ match.court.location_name }}
    {{ match.court.number }}
{% endfor %}

修改但我不明白你为什么要从参与者列表开始,然后调用matches_list。从匹配列表开始,然后上面的代码将起作用。

答案 1 :(得分:0)

我建议使用备用数据结构。而不是每个匹配两行,每个匹配一行。然后,您的数据结构基本上就是您想要的结果“视图”。显然,获胜者将是一个计算的列/值。

然后你的django模型看起来像:

class Match(models.Model):
    player_1 = models.ForeignKey(auth.User)
    score_1 = models.PositiveIntegerField(null=True, blank=True)
    player_2 = models.ForeignKey(auth.USer)
    score_2 = models.PositiveIntegerField(null=True, blank=True)
    court = models.ForeignKey(Court)
    date = models.DateField()

    @property
    def winner(self):
        "None means not played yet, or a draw."
        if self.score_1 > self.score_2:
            return self.player_1
        if self.score_1 < self.score_2:
            return self.player_2

    @property
    def is_draw(self):
        return self.score_1 == self.score_2 and self.score_1 is not None


class Location(models.Model):
    name = models.CharField()

class Court(models.Model):
    location = models.ForeignKey(Location)
    number = models.PositiveIntegerField()