2009-09-16 3 views
6

Ich bin neu in Django und habe ein paar Probleme, meine Gedanken um viele verschiedene Beziehungen und Manytoone (d. H. Fremdschlüssel).Django Relationships

Mein Setup ist dies.

Ich habe Klasse A, Klasse B, Klasse C

Jede Klasse B Objekt zu einer Klasse-A-Objekt gehören. Sie können nicht zu mehr als einem Klasse-A-Objekt gehören. Ein praktischeres Beispiel könnte sein, wenn Klasse A eine Musikband und Klasse B ein Lied mit dieser Band ist. Die meisten Bands haben mehr als einen Song, aber jeder Song muss zu einer Band gehören (in diesem Beispiel kann ein Song niemals mehrere Bands haben).

Klasse C ist eine Auflistung der einzelnen Bandmitglieder. So kann jedem Bandmitglied eine beliebige Anzahl von Songs sowie eine beliebige Anzahl von Bands zugeordnet werden. Mit anderen Worten: ein Mitglied der Band X kann auch ein Mitglied der Band Y.

Meine Frage dann

wäre Wie würde ich die ForeignKey und ManyToMany Beziehungen in diesem Zusammenhang verwenden?

Dieses Beispiel wurde erfunden, um meine Situation leichter verständlich zu machen und mir zu helfen, mein Problem zu erklären. Ich möchte, dass der Administrator für jedes Objekt der Klasse C anzeigt, welche Objekte der Klasse B oder Objekte der Klasse A, denen Klasse C angehört, gehen. Dasselbe gilt für Klasse B und Klasse A.

Wenn Sie Objekte der Klasse A betrachten, sollten Sie in der Lage sein, eine Auflistung aller Objekte der Klasse B zu sehen, die zu dem bestimmten Objekt der Klasse A gehören.

Jeder Eingang geschätzt.

+1

Manytoone eine detaillierte Einführung in die Admin-Anpassung erhalten? Ist das irgendwo in Schottland? – ijw

Antwort

3

Das ist alles ziemlich einfach. Ich habe die folgenden beschreibenden Namen verwendet, um die Verfolgung zu erleichtern.

class Band(models.Model): 
    name = models.CharField(max_length=255) 

class BandMember(models.Model): 
    name = models.CharField(max_length=255) 
    bands = models.ManyToManyField(Band) 

class Song(models.Model): 
    name = models.CharField(max_length=255) 
    band = models.ForeignKey(Band) 

# get a band 
myband = Band.objects.get(name='myband') 

# all songs from that band 
print myband.song_set.all() 

# all members of that band 
print myband.bandmembers.all() 


# get a specific band member 
dave = BandMember.objects.get(name='Dave') 

# what bands is Dave a member of? 
print dave.bands.all() 

# what songs has Dave sung? (slightly more complicated) 
print Song.objects.get(band__bandmember=dave) 
+0

+1 - Gute Antwort - es könnte sich lohnen zu editieren, warum man 'ManyToManyField ('Band')' aber 'ForeignKey (Band)' hat, weil es momentan so aussieht, als ob man 'ManyToManyField' und ' ForeignKey', und nicht mit der Reihenfolge, in der die Klassen definiert wurden. –

+0

Guter Punkt, ich habe tatsächlich die Klassen neu geordnet, so dass es keine Notwendigkeit gibt, die Zeichenfolgenform zu verwenden. –

+0

Hallo Danke für die Antwort. Ich verstehe Ihre Antwort, aber das Problem im Moment ist die Admin-Seite. Wenn ich ein neues BandMember eingebe, werde ich aufgefordert zu sagen, mit welchen Songs er verbunden ist. Und wenn ich ein Bandmitglied öffne, kann ich eine Drop-Liste sehen, die die ID jedes Songs zu enthalten scheint. Wenn ich ein Bandmitglied betrete (welches eine bestimmte ID nr hat - was auch in der Liedtabelle zu finden ist), sobald es erstellt wird, wenn man das Bandmitglied ansieht, sollte der Admin dies anzeigen. Muss ich spezielle Ansichten für den Administrator erstellen, um dies zu tun? – Consiglieri

11

Hier ist, wie ich es einrichten würde (im models.py)

class Member(models.Model): 
    name = models.CharField(max_length=100) 
    ... 

    def __unicode__(self): 
     return self.name 


class Band(models.Model): 
    name = models.CharField(max_length=100) 
    members = models.ManyToManyField(Member) 
    ... 

    def __unicode__(self): 
     return self.name 


class Song(models.Model): 
    name = models.CharField(max_length=100) 
    band = models.ForeignKey(Band) 
    ... 

    def __unicode__(self): 
     return self.name 

wie folgt ein:

  • member.band_set.all() gibt Ihnen alle Bänder ein Mitglied zu
  • gehört
  • band.members.all() gibt Ihnen die Mitglieder einer Band
  • song.band gibt Ihnen die Band für das Lied
  • band.song_set.all() Ihnen alle Songs für eine Band

Hinweis gibt, dass die band_set auf Element und die song_set auf Band sind Beziehungen „Reverse“. Sie sind nicht explizit in den Modellen definiert, aber Django richtet sie transparent für Sie ein. Sie können diese anpassen, indem Sie den Parameter related_name für die Felddefinition verwenden.Beispiel:

class Band(models.Model): 
    members = models.ManyToManyField(Member,related_name='bands') 

würden Sie für ein Mitglied alle Bands erhalten wie folgt:

  • anzeigen alle Mitglieder für eine Band in:

    member.bands.all() 
    

    Der Admin wird die folgenden automatisch bereitstellen eine Multi-Auswahlliste

  • Zeigen Sie die Band für ein Lied in einer einzigen Auswahlliste

Wenn Sie jedoch Songs für eine Band sehen möchten, müssen Sie ein wenig Admin-Anpassung vornehmen.

In Ihrem admin.py:

from django.contrib import admin 

class SongInline(admin.StackedInline): 
    model = Song 
    extra = 1 

class BandAdmin(admin.ModelAdmin): 
    inlines = [SongInline] 

admin.site.register(Band,BandAdmin) 
admin.site.register(Member) 
admin.site.register(Song) 

So können Sie die Songs direkt aus der Admin-Seite zu sehen - und zu bearbeiten oder sie auch hinzufügen! Wenn Sie dieser Vorlage folgen, können Sie alle Bänder für ein Mitglied anzeigen.

Sie können http://docs.djangoproject.com/en/dev/intro/tutorial02/

+0

+1 für die Aufnahme admin.py – Alasdair

+0

Danke, die Antworten kommen so schnell herein, dass ich nicht in der Lage war, aufzuholen :). Ich werde es drehen und sehen, ob ich es mit Ihren Vorschlägen arbeiten kann. – Consiglieri

+0

Hallo nochmal, es scheint zu funktionieren - obwohl es in Band nur ein "memmber object" anzeigt und nicht den Namen des Mitglieds. Ich weiß, dass ich eine list_display machen kann, aber ich weiß nicht, wie man eine list_display auf memebr einer anderen Klasse setzt. dh in der Klasse BandAdmin mit list_display = ('Member.vorname', 'Member.lastname') funktioniert nicht, und wenn ich eine Klasse MemberAdmin mit dem oben genannten list_display einstelle, erhält es eine Liste im Memeber viw, aber die Liste in In der Bandansicht wird immer noch nur ein "Member-Objekt" angezeigt, nicht jedoch der Name des Mitglieds. Ich bin mir sicher, dass das trivial ist, aber würde mir eine helfende Hand zu dieser – Consiglieri

Verwandte Themen