Разница между ForeignKey (User, unique = True) и OneToOneField

Что отличается между models.ForeignKey(Modelname, unique=True) и models.OneToOneField в Django?

Где я должен использовать models.OneToOneField и models.ForeignKey(Modelname, unique=True)?

Ответ 1

OneToOneField очень похож на ForeignKey с unique=True. Если вы не используете множественное наследование таблиц, в этом случае вам нужно использовать OneToOneField, единственное реальное различие - это api для доступа к связанным объектам.

В документах Django говорится:

Концептуально это похоже на ForeignKey с unique=True, но "обратная" сторона отношения будет напрямую возвращать один объект.

Покажем, что это значит с примером. Рассмотрим две модели: " Person и Address. Мы предположим, что у каждого человека есть уникальный адрес.

class Person(models.Model):
    name = models.CharField(max_length=50)
    address = models.ForeignKey('Address', unique=True)

class Address(models.Model):
    street = models.CharField(max_length=50)

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

address = person.address

Однако, если вы начинаете с адреса, вам нужно пройти через диспетчер person_set чтобы получить человека.

person = address.person_set.get() # may raise Person.DoesNotExist

Теперь замените ForeignKey на OneToOneField.

class Person(models.Model):
    name = models.CharField(max_length=50)
    address = models.OneToOneField('Address')

class Address(models.Model):
    street = models.CharField(max_length=50)

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

address = person.address

И теперь мы можем легко получить доступ к человеку из адреса.

person = address.person # may raise Person.DoesNotExist

Ответ 2

Когда вы получаете доступ к OneToOneField вы получаете значение поля, которое вы запрашивали. В этом примере поле "title" в книжной модели - OneToOneField:

>>> from mysite.books.models import Book
>>> b = Book.objects.get(id=50)
>>> b.title
u'The Django Book'

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

>>> b = Book.objects.get(id=50)
>>> b.publisher
<Publisher: Apress Publishing>
>>> b.publisher.website
u'http://www.apress.com/'

С ForeignKey полей ForeignKey работают и наоборот, но они немного отличаются из-за несимметричного характера отношений.

>>> p = Publisher.objects.get(name='Apress Publishing')
>>> p.book_set.all()
[<Book: The Django Book>, <Book: Dive Into Python>, ...]

За кулисами book_set - это всего лишь QuerySet и его можно фильтровать и нарезать, как и любой другой QuerySet. Имя book_set атрибута создается путем добавления имени модели нижнего регистра в _set. Надеюсь, это поможет проиллюстрировать различия между созданными отношениями.