Агрегация Джанго через обратную связь - PullRequest
9 голосов
/ 04 мая 2010

Учитывая эти две модели:

class Profile(models.Model):
    user = models.ForeignKey(User, unique=True, verbose_name=_('user'))
    about = models.TextField(_('about'), blank=True)
    zip = models.CharField(max_length=10, verbose_name='zip code', blank=True)
    website = models.URLField(_('website'), blank=True, verify_exists=False)

class ProfileView(models.Model):
    profile = models.ForeignKey(Profile)
    viewer = models.ForeignKey(User, blank=True, null=True)
    created = models.DateTimeField(auto_now_add=True)

Я хочу отсортировать все профили по количеству просмотров. Я могу получить список идентификаторов профилей, отсортированных по общему количеству просмотров:

ProfileView.objects.values('profile').annotate(Count('profile')).order_by('-profile__count')

Но это всего лишь словарь идентификаторов профилей, а это значит, что мне нужно затем зациклить его и составить список объектов профиля. Который является рядом дополнительных запросов и все еще не приводит к QuerySet. В этот момент я мог бы также перейти на сырой SQL. Прежде чем я это сделаю, есть ли способ сделать это из модели профиля? ProfileViews связаны через поле ForeignKey, но модель Profile не знает об этом, поэтому я не уверен, как связать их вместе.

Кроме того, я понимаю, что могу просто сохранить представления как свойство модели Profile, и это может оказаться тем, чем я занимаюсь здесь, но я все еще заинтересован в том, чтобы узнать, как лучше использовать функции агрегирования.

Ответы [ 2 ]

11 голосов
/ 04 мая 2010

ProfileViews связаны через поле ForeignKey, но модель профиля не знает, что

Модель профиля действительно знает это. Вы должны быть в состоянии сделать что-то вроде:

  Profile.objects.all().annotate(count_views=Count('profileview__pk')).order_by('count_views')

Редактировать : Здесь вы можете найти документы Django о поисках, которые охватывают отношения http://docs.djangoproject.com/en/dev/topics/db/queries/#lookups-that-span-relationships

4 голосов
/ 04 мая 2010

Конечно, это будет работать:

Profile.objects.all().annotate(viewcount=Count('profileview')).order_by('-viewcount')

Как говорит Ботондус, модель Profile знает об обратном отношении ForeignKey.

...