#django #django-models #many-to-many
#django #django-модели #многие ко многим
Вопрос:
У меня есть эта модель «jobs» (показана ниже).
- Между хостами и местоположениями существует отношение M2M (местоположению назначено несколько хостов).
- У меня также есть класс Timezone с отношением внешнего ключа, определенным между местоположением и часовым поясом (местоположению присваивается часовой пояс)
Проблема, с которой я сталкиваюсь, заключается в том, что я не могу отменить комментарий к элементу ‘colo’ в классе Host из-за ссылки внешнего ключа на «Местоположение». Класс Location определяется после класса Host. Но я не могу переместить определение местоположения выше класса Host из-за ссылки M2M на «hosts» в классе Location.
Я что-то упускаю концептуально? Любая помощь была бы высоко оценена!
Вот соответствующая часть моей модели:
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)
Ответ №1:
В принципе, вы не можете ссылаться на класс Location до того, как он был определен. Итак, если вы измените порядок классов хоста и местоположения, это поможет. Тогда отношение «многие ко многим» относится к классу хоста, который еще не определен. Но поскольку отношения «многие ко многим» могут быть определены в любой таблице, просто переместите ее в класс 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. спасибо за быстрый ответ, но у хоста будет только одно местоположение — местоположение, в котором он находится.
2. Но у вас есть отношение «многие ко многим», определенное в вашем классе Location, к классу Host?
3. Это не имеет отношения к вашему вопросу, но вы можете захотеть проверить django-timezones для вашей модели часового пояса. В нем есть несколько приятных функций, которые могут уменьшить некоторую головную боль, связанную с часовыми поясами. github.com/brosner/django-timezones
Ответ №2:
У вас есть отношения «многие ко многим» между хостами и местоположениями, однако вы хотите, чтобы хосты имели одно и то же местоположение, вы на самом деле хотите отношения «один ко многим» между хостами и местоположениями. Это объявлено с использованием моделей.Внешний ключ, который у вас есть в вашем классе хоста. Вам просто нужно изменить порядок кода, чтобы класс 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)
Я не был уверен в лучшем способе сделать это, поэтому я просто собираюсь написать другой ответ. Мой первый ответ, по сути, позволил нначефски создать модель, которую он определил в вопросе. Прочитав его комментарии, я понял, что он на самом деле хотел модель, которая немного отличается от той, которую он определил.
Ответ №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 об обратных отношениях
Комментарии:
1. Ах ха! Это именно то, что мне было нужно. Я не должен беспокоиться об определении обратных отношений в модели. Я должен использовать наборы запросов и фильтры, чтобы, на мой взгляд, изменить отношения, когда это необходимо. Спасибо!!!