В чем разница между OneToOne, ManyToMany и полем ForeignKey в Джанго?

У меня возникли некоторые трудности с головой вокруг отношений в моделях Django.

может кто-нибудь объяснить, в чем разница между OneToOne, ManyToMany и ForeignKey?

1 ответов


Ну, здесь по существу два вопроса:

  1. в чем разница (в общем) Между один к одному, многие ко многим, и отношения внешнего ключа
  2. каковы их различия, характерные для Django.

на оба этих вопроса довольно легко ответить с помощью простого поиска Google, но, поскольку я не могу найти точный обман этого вопроса на SO, я пойду вперед и отвечу.

обратите внимание, что в Django, отношения должно быть определено только с одной стороны отношений.


иностранный ключ

отношение внешнего ключа обычно известно как отношение "многие к одному". Обратите внимание, что обратная сторона этого отношения-один ко многим (который Django предоставляет инструменты для доступа). Как следует из названия, многие объекты могут быть связаны с одной.

Person <--> Birthplace
class Birthplace(models.Model):
    city = models.CharField(max_length=75)
    state = models.CharField(max_length=25)

    def __unicode__(self):
        return "".join(self.city, ", ", self.state)

class Person(models.Model):
    name = models.CharField(max_length=50)
    birthplace = models.ForeignKey(Birthplace)

    def __unicode__(self):
        return self.name

вы можете видеть, что никакие отношения не определены в Birthplace модель, и ForeignKey отношение определяется в пределах Person модель. Скажем, мы создаем следующие модели (очевидно, не в синтаксисе Python):

  • Место Рождения: Даллас, Штат Техас
  • Место Рождения: Нью-Йорк, Нью-Йорк
  • Персона: Джон Смит, Место Рождения: (Даллас, Техас)
  • Лицо: Мария Ли, Место Рождения: (Даллас, Техас)
  • Человек: Дэниел Ли, Место Рождения: (Нью-Йорк, Нью-Йорк)

теперь мы можем видеть, как Django позволяет нам использовать эти отношения (обратите внимание, что ./manage.py shell - ваш друг!):

>> from somewhere.models import Birthplace, Person
>> Person.objects.all()
[<Person: John Smith>, <Person: Maria Lee>, <Person: Daniel Lee>]
>> Birthplace.objects.all()
[<Birthplace: Dallas, Texas>, <Birthplace: New York City, New York>]

вы можете увидеть наши созданные модели. Теперь давайте проверим чье-то место рождения:

>> person = Person.object.get(name="John Smith")
>> person.birthplace
<Birthplace: Dallas, Texas>
>> person.birthplace.city
Dallas

предположим, вы хотите видеть всех людей с данным местом рождения. Как я уже говорил ранее, Django позволяет получить доступ к обратным отношениям. От по умолчанию Django создает менеджер (RelatedManager) на вашей модели, чтобы справиться с этим, названный <model>_set, где <model> - название модели в нижнем регистре.

>> place = Birthplace.objects.get(city="Dallas")
>> place.person_set.all()
[<Person: John Smith>, <Person: Maria Lee>]

обратите внимание, что мы можем изменить имя этого менеджера, установив related_name аргумент ключевого слова в нашем модельном отношении. Итак, мы изменим : приказ: []

  • проект: заказы: [(заказ: "космический корабль", "НАСА")]
  • проект: заказы: [(заказ: "космический корабль", "НАСА"), (заказ: "гоночный автомобиль", "НАСКАР")]
  • мы можем получить доступ к этим отношениям следующим образом:

    >> Project.objects.all()
    [<Project: Project 0>, <Project: Project 1>, <Project: Project 2>]
    >> for proj in Project.objects.all():
    ..     print(proj)
    ..     proj.orders.all()  # Note that we must access the `orders`
    ..                        # field through its manager
    ..     print("")
    Project 0
    []
    
    Project 1
    [<Order: Spaceship for NASA>]
    
    Project 2
    [<Order: Spaceship for NASA>, <Order: Race car for NASCAR>]
    

    обратите внимание, что заказ НАСА связано с 2 проектами, а заказ ВМС США не связан ни с одним. Также обратите внимание, что один проект не имеет заказов, а один имеет несколько.

    мы также можем получить доступ к отношениям в обратном порядке так же, как и раньше:

    >> order = Order.objects.filter(customer="NASA")[0]
    >> order.project_set.all()
    [<Project: Project 0>, <Project: Project 2>]
    

    ресурсы

    хорошее объяснение отношений БД предоставлено @MarcB

    страница Википедии о мощности

    Джанго Docs:

    models.ForeignKey

    models.OneToOneField

    models.ManyToManyField

    один-к-одному отношения

    многие-ко-многим отношения