Django关系

时间:2009-09-16 12:22:41

标签: django django-models django-admin

我是Django的新手,并且在涉及多种关系和Manytoone(即外键)时遇到了一些问题。

我的设置是这样的。

我有A班,B班,C班

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

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

我的问题就是

我将如何在此上下文中使用ForeignKey和ManytoMany关系?

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

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

任何和所有输入都赞赏。

2 个答案:

答案 0 :(得分: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/

获得有关管理员自定义的更详细介绍

答案 1 :(得分: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)