2009-09-16 38 views
6

我是Django的新成员,并且有几个问题引起我对许多关系和Manytoone(即外键)的思考。Django关系

我的设置是这样的。

我有A类,B类,C类

每个B类对象必须属于A类对象。它们不能属于多个A类对象。如果A类是音乐乐队而B类是带有该乐队的歌曲,则更实际的例子是。大多数乐队将有多首歌曲,但每首歌曲都必须属于乐队(在这个例子中,一首歌曲永远不会有多个乐队)。

C类是个别乐队成员的列表。所以每个乐队成员都可以与任意数量的歌曲以及任意数量的乐队相关联。换句话说带X的成员,也可以是带Y的成员

我的问题则是

我怎么会使用ForeignKey的和多对多关系,在这种情况下?

这个例子只是为了让我的情况更容易理解,帮助我解释我的问题。我希望管理员为每个C类对象显示类C所属的类B对象或类A对象。对于B类和A类也是如此。

如果您查看A类对象,应该能够列出属于该特定A类对象的所有B类对象。

任何和所有输入赞赏。

+1

Manytoone?那是在苏格兰的某个地方吗? – ijw 2009-09-16 12:26:10

回答

3

这是非常简单的。我已经使用了下面的描述性名称,以便更容易遵循。

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 - 好的答案 - 可能值得编辑为什么你有'ManyToManyField('Band')',但是'ForeignKey(Band)',因为目前看起来就像你必须定义'ManyToManyField'和' ForeignKey“,而不是用于定义类的顺序。 – 2009-09-16 12:51:22

+0

好点,我已经重新排序了类,所以不需要使用字符串表单。 – 2009-09-16 12:53:38

+0

嗨 感谢您的回复。我理解你的答案,但目前的问题是管理页面。如果我输入新的乐队成员,系统会提示他说出他所连接的歌曲。如果我打开乐队成员,我可以选择一个似乎包含每首歌曲的ID的下拉列表。 如果我在乐队记忆中创建了一个乐队成员(它有一个特定的编号 - 也可以在歌曲表中找到),管理员应该显示该乐队成员。我必须为管理员创建特殊视图才能执行此操作吗? – Consiglieri 2009-09-16 12:57:37

11

下面是我设置它(在你的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 

设置是这样的:

  • member.band_set.all()给你一个成员所属的所有乐队
  • band.members.all()为您提供乐队成员
  • song.band给你带的那首歌
  • band.song_set.all()为您提供了所有歌曲的乐队

注意,band_set的成员,并带了song_set是“反向”的关系。它们没有在模型中明确定义,但Django透明地为您设置它们。您可以通过在字段定义上使用related_name参数来自定义这些参数。例如:

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

会让你得到一个成员的所有波段如下:在一个乐队

  • 显示所有成员:

    member.bands.all() 
    

    管理员会自动提供以下多选列表

  • 在单个选择列表中显示歌曲的乐队

但是,如果你想看乐队的歌曲,你必须做一些管理定制。

在你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) 

这将让您从管理页面右侧的歌曲 - 和编辑,或添加他们的!按照这个模板,你也可以显示一个成员的所有乐队。

你可以得到更详细的介绍给管理定制http://docs.djangoproject.com/en/dev/intro/tutorial02/

+0

+1为包括admin.py – Alasdair 2009-09-16 12:53:53

+0

谢谢,答案是如此之快,我没能赶上:)。 我会给它旋转,看看我能不能与你的建议。 – Consiglieri 2009-09-16 12:59:45

+0

嗨,它似乎工作 - all带inlky显示一个“memmber对象”,而不是成员的名称。我知道我可以做一个list_display,但我不知道如何在另一个类的memebr上设置list_display。即班级BandAdmin中使用list_display =('Member.firstname','Memeber.lastname')不起作用,如果我设置了一个类MemberAdmin与上面提到的list_display它获得列表显示在Memeber viw中,但列表中乐队视图仍然只显示“成员对象”,但不显示成员的名称。我敢肯定,这是微不足道的,但会很乐意在这个 – Consiglieri 2009-09-16 14:11:36