2010-05-04 3 views
7

Compte tenu de ces deux modèles:Django l'agrégation des relations inversée

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) 

Je veux obtenir tous les profils classés par vues au total. Je peux obtenir une liste des ids profil triées par vues au total avec:

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

Mais c'est juste un dictionnaire de ids de profil, que je signifie ai alors en boucle sur elle et mis en place une liste d'objets de profil. Ce qui est un nombre de requêtes supplémentaires et ne génère toujours pas de QuerySet. À ce stade, je pourrais aussi bien tomber au SQL brut. Avant de le faire, existe-t-il un moyen de le faire à partir du modèle Profile? ProfileViews sont liés via un champ ForeignKey, mais ce n'est pas comme si le modèle Profile le savait, donc je ne sais pas comment lier les deux ensemble. En passant, je me rends compte que je pouvais simplement stocker des vues en tant que propriété sur le modèle Profile et cela pourrait être ce que je fais ici, mais je suis toujours intéressé à apprendre à mieux utiliser les fonctions d'agrégation.

Répondre

9

ProfileViews sont liés par un champ ForeignKey, mais ce n'est pas comme si le modèle de profil sait que

Le modèle de profil ne fait savoir que. Vous devriez être en mesure de faire quelque chose comme:

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

Modifier: Vous pouvez trouver Django docs sur les recherches qui couvrent les relations http://docs.djangoproject.com/en/dev/topics/db/queries/#lookups-that-span-relationships

+0

'à partir de django.db.models import Count' – juanjo

3

Sûrement ceci fonctionne:

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

Comme Botondus dit, le modèle de profil est conscient de la relation inverse de ForeignKey.