开发者

django model problem with M2M and Foreign Key relationships

I have this "jobs" model (shown below).

  • There is a M2M relationship between Hosts and Locations(A location has multiple hosts assigned to it).
  • I also have a Timezone class with a Foreign Key relationship defined between location and timezone(A location is assigned a timezone)

The problem I'm having is that i cannot un-comment the 'colo' item in the Host class because of the foreign key reference to "Location". The Location class is defined after the Host class. But i cannot move the definition of the Location to above the Host class because of the M2M reference for "hosts" in the Location class.

Am i missing something conceptually? Any help would be greatly appreciated!

Here is the relevant part of my model:

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.Fo开发者_C百科reignKey(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)


Basically, you can't reference the Location class before it has been defined. So if you switch the order of the Host and Location classes that helps. Then the many to many relationship refers to the Host class which isn't defined yet. But since the many to many relationships can be defined on either table just move it to the Host class. Here is the modified code:

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)


You have a many to many relationship between hosts and locations, however, what you want is to allow hosts to have the same location you actually want a one to many relationship between hosts and locations. This is declared using the models.ForeignKey that you have in your Host class. You just have to re-order the code so that the Host class appears after the Location class, allowing you to reference it. Also you can remove the many-many relationship.

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)

I wasn't sure of the best way to do this so I'm just going to write another answer. My first answer basically, allowed nnachefski to create the model he defined in the question. After reading his comments I realized he actually wanted a model that is slightly different from the one he defined.


Since a Host will only ever have one location, you can remove the locations field from the host model, or remove colo, and change locations to location = models.ForeignKey(Location)

To get all hosts from a location, you can do

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

Here's a link to the Django docs about backwards relationships

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜