2016-04-26 1 views
1

Erste, hier sind meine Modelle. Jede Saite hat von 1 bis 3 Darsteller, jeder Darsteller auf mehrere Saiten verbunden:Django Query Set gibt Attribut_Fehler, wenn Sie versuchen, ein Set mit mehreren Fremdschlüsseln

class Performer(models.Model) : 
    name = models.CharField(max_length=60, default="None") 
    description = models.TextField(null=True, default=None) 

class String(models.Model) : 
    index = models.IntegerField(null=True, default=None) 
    step = models.IntegerField(null=True, default=None) 
    process = models.CharField(max_length=100,null=True, default=None) 
    description = models.TextField(null=True, default=None) 
    performer = models.ForeignKey(Performer, related_name='performer', on_delete=models.CASCADE, null=True, default=None) 
    performer2 = models.ForeignKey(Performer, related_name='performer2', on_delete=models.CASCADE, null=True, default=None) 
    performer3 = models.ForeignKey(Performer, related_name='performer3', on_delete=models.CASCADE, null=True, default=None) 

Ich brauche alle Strings machen auf Interpreten zusammen. Allerdings, wenn ich versuche string_set zu verwenden, um alle Strings zu erhalten, wenn eine des Performer Fremdschlüssels zu dieser Zeichenfolge zeigen, wie so:

p = Performer.objects.get(name="smth")# so p is a performer object 
s = p.string_set.all() 

ich dieses Problem bekommen:

AttributeError: 'Performer' object has no attribute 'string_set' 

Auch habe ich tryed Filter mit verwandtem Namen zu verwenden, aber das gibt mir den gleichen Fehler. Gibt es eine Möglichkeit, ein _set basierend auf einem beliebigen Fremdschlüsselfeld zu erhalten, das alle auf denselben Typ verweist?

Antwort

3

Durch related_name Bereitstellung in jeder performer, performer2, performer3 Beziehungen Sie die Standardeinstellung überschreiben related_name von Performer Klasse verbindet die string_set wäre. Jetzt die String für jede dieser Beziehungen bekommen würden Sie sie wie folgt erhalten müssen:

p = Performer.objects.get(name="smth")# so p is a performer object 
p.performer.all() #first one which would actually be a queryset 
p.performer1.all() #second one which would actually be a queryset 
p.performer2.all() #third one which would actually be a queryset 

Dies ist nur wahr wäre, wenn man einzelne String und einzelne Performer miteinander verwandt, aber Sie sollten im Auge behalten, diese Abfrage wie p.performer1.all() kann tatsächlich 2 oder mehr String Objekte zurückgeben, die eine Beziehung mit diesem Performer haben würde. Dies würde die Dinge noch mühsamer machen.

Beachten Sie, dass die ForeignKey einer Eins-zu-viele-Beziehung schafft ...

Die Modelle Struktur müssten Sie bieten Probleme mit Filtern tun Sie wollen. Die bessere Design-Modell würde wie folgt aussehen:

class Performer(models.Model) : 
    name = models.CharField(max_length=60, default="None") 
    description = models.TextField(null=True, default=None) 
    strings = models.ManyToManyField(String, related_name='performers') 

class String(models.Model) : 
    index = models.IntegerField(null=True, default=None) 
    step = models.IntegerField(null=True, default=None) 
    process = models.CharField(max_length=100,null=True, default=None) 
    description = models.TextField(null=True, default=None) 

Dieser Entwurf Sie ausführen lassen würde:

mit ManyToManyField für diese Idee
p = Performer.objects.get(name="smth")# so p is a performer object 
s = p.strings.all() 
+0

Danke, es i 'll Versuch zuerst .. –

+0

Aber ich kann Führen Sie "s.performers.all()" aus, wobei s ein einzelnes String-Objekt mit diesen Modellen ist? –

+0

Ja, Sie können. Aber bedenken Sie, dass es die Viele-zu-Viele-Beziehung so 's.performers.all()' auch ein Abfrage-Set zurückgeben würde, kein einzelnes Objekt – canufeel