【问题标题】:django model problem with M2M and Foreign Key relationshipsM2M 和外键关系的 django 模型问题
【发布时间】:2011-05-06 15:18:36
【问题描述】:

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

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

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

我在概念上错过了什么吗?任何帮助将不胜感激!

这是我模型的相关部分:

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)

【问题讨论】:

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


    【解决方案1】:

    基本上,您不能在定义之前引用 Location 类。因此,如果您切换 Host 和 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)
    

    【讨论】:

    • 感谢您的快速响应,但主机只有一个位置,即它所在的托管位置。
    • 但是您在 Location 类中定义了与 Host 类的多对多关系?
    • 这与您的问题无关,但您可能想为您的时区模型检查 django-timezones。它有一些不错的功能,可以减少与时区有关的一些麻烦。 github.com/brosner/django-timezones
    【解决方案2】:

    您在主机和位置之间存在多对多关系,但是,您想要的是允许主机具有与您实际希望主机和位置之间的一对多关系相同的位置。这是使用您在 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 创建他在问题中定义的模型。在阅读了他的 cmets 之后,我意识到他实际上想要一个与他定义的模型略有不同的模型。

    【讨论】:

      【解决方案3】:

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

      要从一个位置获取所有主机,您可以这样做

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

      这是 Django docs about backwards relationships的链接

      【讨论】:

      • 啊哈!这正是我所需要的。我不应该担心在模型中定义后向关系。我应该在需要时使用查询集和过滤器来反转我的视图中的关系。谢谢!!!
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-05-27
      • 2013-01-03
      • 1970-01-01
      • 2018-01-10
      • 2013-08-17
      • 2010-10-22
      • 2023-01-26
      相关资源
      最近更新 更多