Агрегирование данных с использованием ORM - PullRequest
1 голос
/ 13 февраля 2011

Джанго / Питон нуб здесь!

Вот мои модели:

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 ]

1 голос
/ 13 февраля 2011

Ваша таблица, показывающая «данные в базе данных», не соответствует вашим моделям, поэтому я немного запутался.

Но, исходя из ваших моделей, здесь нет необходимости в агрегировании, так как у вас естьполе 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.Начните со списка совпадений, затем приведенный выше код будет работать.

0 голосов
/ 14 февраля 2011

Я бы предложил альтернативную структуру данных. Вместо двух строк на совпадение, используйте одну строку на совпадение. Тогда ваша структура данных в основном то, что вы хотите в качестве «просмотра» результатов. Очевидно, что победителем будет вычисляемый столбец / значение.

Тогда ваши модели 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()
...