2017-02-27 1 views
0

Je travaille actuellement sur une fonction API qui retournerait une liste d'amis utilisateurs ainsi que toutes les références pour les photos de ces utilisateurs. (Bien que j'ai seulement besoin de la référence triée par ord)Prefetching relation un-à-plusieurs django ORM

Voici mes modèles avec les clés étrangères.

class Personimage(models.Model): 
    photo_uuid = models.CharField(db_column='photoUUID', max_length=100, blank=True, 
           primary_key=True, default='') 
    user_id = models.ForeignKey('Member', db_column='userID', on_delete=models.CASCADE, blank=True, 
           null=True) 
    ord = models.IntegerField(db_column='ord', blank=True, null=True) 
    reference = models.CharField(db_column='reference', max_length=200, blank=True, null=True) 

class Member(AbstractBaseUser): 
    user_id = models.CharField(db_column='userID') 

class Friends(models.Model): 
    id = models.IntegerField(db_column='id', primary_key=True, blank=False, null=False) 
    puser = models.ForeignKey('Member', on_delete=models.CASCADE, db_column='puser') 
    suser = models.ForeignKey('Member', on_delete=models.CASCADE, db_column='suser', 
           related_name='secondary_friend') 

Jusqu'à présent, j'ai pu le faire:

friends = Friend.objects.filter(puser=cur_user).prefetch_related('suser') 

    for r in friends: 
     photos = Personimage.objects.filter(user_id=r.suser) 
     united.append({'user_id': r.suser.user_id, 
         'name': r.suser.name, 
         'photos': [photo.reference for photo in photos.filter(user_id=r.suser)]}) 

mais comme vous pouvez l'image qui est incroyablement lent car il doit faire un appel à la table Personimage pour chaque utilisateur dans la liste d'amis . Je sais qu'il existe un moyen de le faire en utilisant prefetch_related ou une combinaison de cela et d'autre chose, mais je ne trouve pas comment le faire n'importe où en ligne ou dans mon expérimentation. Le plus proche que j'ai eu était de retourner une seule photo pour chacun des membres des amis.

+0

Pourquoi avez-vous créé le modèle Amis? Ne serait-il pas plus facile d'ajouter un friends = models.ManyToManyField ('self') à la classe Member? –

+0

@RomanB. Je l'ai créé parce que je pensais que j'avais besoin de la table de jonction pour la relation de plusieurs à plusieurs. Je suis assez nouveau à l'utilisation de l'ORM Django –

+0

Et pourquoi utilisez-vous db_column pour chaque domaine? Contrôlez-vous/créez-vous les tables dans Django ou vous essayez simplement de créer une API dans Django pour les tables existantes? Cherchez-vous une solution sans avoir à changer les tables ou vous pouvez les modifier pour que cela fonctionne mieux? –

Répondre

0

Remplacez le modèle Friends par un champ ManyToMany 'friends' dans la classe Member. Aussi, je ne pense pas que vous ayez besoin du champ user_id - vous avez le champ 'id' par défaut, vous n'avez pas besoin de l'alias pour cela (Django le fera pour vous).

class Member(AbstractBaseUser): 
    friends = models.ManyToManyField('self') 

ensuite pour obtenir les données sous la forme que vous vouliez:

friends = Member.objects.get(pk=cur_user).friend.all().prefetch_related('personimage_set') 
united = [] 
for friend in friends: 
    united.append({'user_id': friend.id, 
       'name': friend.name, 
       'photos': list(friend.personimage_set.values_list('reference', flat=True))})