2017-02-27 9 views
0

Ich arbeite gerade an einer API-Funktion, die eine Liste von Freunden eines Benutzers sowie alle Referenzen für diese Benutzer Fotos zurückgeben würde. (Obwohl ich die Referenz nur sortiert nach ord benötigen)Prefetching Eins-zu-viele-Beziehung django ORM

Unten sind meine Modelle mit den Fremdschlüsseln.

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') 

Bisher war ich in der Lage, dies zu tun:

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)]}) 

aber wie können Sie Bild, das unglaublich langsam ist, wie es für jeden Benutzer in der Freundesliste einen Aufruf an die Personimage Tisch zu machen hat . Ich weiß, dass es einen Weg gibt, dies mit prefetch_related oder einer Kombination aus ihm und etwas anderem zu tun, aber ich kann nirgendwo online oder in meinen Experimenten finden, wie ich es mache. Das nächste, was ich bekam, war, dass ich nur ein Foto für jedes Mitglied in Freunden zurückgab.

+0

Warum Sie die Freunde Modell erstellt haben? Wäre es nicht einfacher, der Member-Klasse ein friends = models.ManyToManyField ('self') hinzuzufügen? –

+0

@RomanB. Ich habe es erstellt, weil ich dachte, ich brauche den Tisch für die Beziehung von Vielen zu Vielen. Ich bin ziemlich neu in der Verwendung der Django ORM –

+0

Und warum verwenden Sie db_column für jedes Feld? Steuern/erstellen Sie die Tabellen in Django oder versuchen Sie gerade, eine API in Django für vorhandene Tabellen zu erstellen? Suchen Sie nach einer Lösung, ohne die Tabellen ändern zu müssen, oder Sie können sie ändern, damit sie besser funktioniert? –

Antwort

0

Ersetzen Sie das Friends-Modell durch ein ManyToMany-Feld "friends" in der Member-Klasse. Auch ich glaube nicht, dass Sie das Feld user_id benötigen - Sie haben das Standardfeld 'id', Sie brauchen nicht den Alias ​​dafür (Django macht es für Sie).

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

dann die Daten in Form bekommen Sie wollten:

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))})