我是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类对象的列表。
任何和所有输入都赞赏。
答案 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)
这将让您直接从管理页面查看歌曲 - 并编辑或添加它们!通过遵循此模板,您还可以显示成员的所有乐队。
获得有关管理员自定义的更详细介绍答案 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)