具有M2M和外键关系的django模型问题

时间:2011-05-06 15:18:37

标签: django django-models many-to-many

我有这个“工作”模式(如下所示)。

  • 主机和位置之间存在M2M关系(一个位置分配了多个主机)。
  • 我还有一个Timezone类,在位置和时区之间定义了一个外键关系(一个位置被分配了一个时区)

我遇到的问题是我无法取消注释Host类中的'colo'项,因为外键引用了“Location”。 Location类是在Host类之后定义的。但是我无法将Location的定义移到Host类之上,因为Location类中的“hosts”的M2M引用。

我是否在概念上遗漏了什么?任何帮助将不胜感激!

以下是我模型的相关部分:

class Timezone(models.Model):
    name = models.CharField(max_length=32, unique=True)
    def __unicode__(self):
        return "%s"%(self.name)

class Host(models.Model):
    name = models.CharField(max_length=32, unique=True)
#    colo = models.ForeignKey(Location)
    def __unicode__(self):
        return "%s"%(self.name)

class Location(models.Model):
    name = models.CharField(max_length=3, unique=True)
    hosts = models.ManyToManyField(Host, blank=True) #not required
    tz = models.ForeignKey(Timezone)
    def __unicode__(self):
        return "%s"%(self.name)

3 个答案:

答案 0 :(得分:1)

基本上,在定义之前,您无法引用Location类。因此,如果您切换主机和位置类的顺序有帮助。然后,多对多关系指的是尚未定义的Host类。但是,由于可以在任一表上定义多对多关系,只需将其移动到Host类即可。这是修改后的代码:

class Timezone(models.Model):
    name = models.CharField(max_length=32, unique=True)
    def __unicode__(self):
        return "%s"%(self.name)

class Location(models.Model):
    name = models.CharField(max_length=3, unique=True)    
    tz = models.ForeignKey(Timezone)
    def __unicode__(self):
        return "%s"%(self.name)

class Host(models.Model):
    name = models.CharField(max_length=32, unique=True)
    colo = models.ForeignKey(Location, related_name='colocation')
    locations = models.ManyToManyField(Location, blank=True) #not required
    def __unicode__(self):
        return "%s"%(self.name)

答案 1 :(得分:1)

主机和位置之间存在多对多关系,但是,您希望允许主机具有您实际想要的主机和位置之间的一对多关系的相同位置。这是使用您在Host类中拥有的models.ForeignKey声明的。您只需重新排序代码,以便Host类出现在Location类之后,允许您引用它。你也可以删除许多关系。

class Timezone(models.Model):
    name = models.CharField(max_length=32, unique=True)
    def __unicode__(self):
        return "%s"%(self.name)    

class Location(models.Model):
    name = models.CharField(max_length=3, unique=True)
    tz = models.ForeignKey(Timezone)
    def __unicode__(self):
        return "%s"%(self.name)

class Host(models.Model):
    name = models.CharField(max_length=32, unique=True)
    colo = models.ForeignKey(Location)
    def __unicode__(self):
        return "%s"%(self.name)

我不确定最好的方法,所以我只想写另一个答案。基本上我的第一个答案是,允许nnachefski创建他在问题中定义的模型。在阅读他的评论后,我意识到他实际上想要一个与他定义的模型略有不同的模型。

答案 2 :(得分:0)

由于主机只有一个位置,您可以从主机模型中删除locations字段,或删除colo,然后将locations更改为location = models.ForeignKey(Location) < / p>

要从某个位置获取所有主机,您可以执行

location = Location.objects.get(pk=1)
hosts = location.host_set.all() #returns all hosts for the location

这是Django docs about backwards relationships

的链接