2011-01-07 4 views
2

У меня есть три модели, Претендент, Неделя и Vote, каждый соперник может иметь голоса, основанные на неделе,Можно ли аннотировать запрос Django ORM со сложным запросом

class Contender(models.Model) 
    week = models.ManyToManyField(Week) 

class Week(models.Model): 
    date_start = models.DateField() 

class Vote(models.Model): 
    contender = models.ForeignKey(Contender) 
    week = models.ForeignKey(Week) 

Я хотел бы добавить что-то Претендент, так что я сделал это:

c = Count('vote', vote__week__date_start = "2011-01-03") 
contenders = Contender.objects.all().annotate(vote_count=c).order_by('-vote_count') 
contenders[0].vote_count 

проблема заключается в том, что, когда я добавить голос с другой неделей (то есть date_start с различным) .vote_count значения изменяется, и, таким образом, кажется, что дополнительные параметры переходят объект Count не имеет значения.

Как это сделать аннотацию в Django ORM?

ответ

3

Вы могли бы начать с Голосовать:

votes = Vote.objects.filter(week__date_start = "2011-01-03")  \ 
        .values_list('contender')      \ 
        .annotate(cnt=Count('week')).order_by('-cnt') 
contender_pks = [d[0] for d in votes] 
contenders_dict = Contender.objects.in_bulk(contender_pks) 

contenders = [] 
for pk, vote_count in votes: 
    contender = contenders_dict[pk] 
    contender.vote_count = vote_count 
    contenders.append(conteder) 

Кроме того, вы можете сделать некоторые денормализация - добавить

class VoteCount(models.Model): 
    contender = models.ForeignKey(Contender) 
    week = models.ForeignKey(Week) 
    count = models.IntegerField(default=0) 

и подсчет голосов в нем (переопределение Vote.save() или с помощью post_save сигнала) , то вы просто выполните:

VoteCount.objects.filter(week__date_start = "2011-01-03") \ 
       .select_related('contender')    \ 
       .order_by('-count') 

Это будет намного эффективнее, часто.

Смежные вопросы