Сохранение учетных данных Google в Django: используйте для пользователя пользовательский интерфейс ForeignKey или OneToOneField? [dубликат]

В чем разница между django OneToOneField и ForeignKey?

282
задан 31 December 2016 в 01:27

5 ответов

OneToOneField (взаимно-однозначный) реализует в объектной ориентации понятие композиции, в то время как ForeignKey (один-ко-многим) относится к агрегированию.

10
ответ дан 15 August 2018 в 15:34

A ForeignKey для одного-ко-многим, поэтому объект Car может иметь много колес, каждое колесо имеет ForeignKey для автомобиля, к которому он принадлежит. OneToOneField будет похож на движок, в котором объект Car может иметь один и только один.

82
ответ дан 15 August 2018 в 15:34
  • 1
    спасибо, Доза OneToOneField (someModel) означает ForeignKey (SomeModel, unique = True)? – redice 3 May 2011 в 19:13
  • 2
    Да: «OneToOneField по сути тот же, что и ForeignKey, за исключением того, что всегда имеет« уникальный ». ограничение с ним, а обратное отношение всегда возвращает объект, на который указывает (поскольку его будет только когда-либо), вместо того, чтобы возвращать список. ' – Dan Breen 3 May 2011 в 19:18
  • 3
    Как насчет нескольких автомобилей с одним и тем же двигателем? – Oleg Belousov 5 December 2013 в 05:04
  • 4
    @OlegTikhonov У них может быть копия того же самого дизайна двигателя, но мне бы хотелось увидеть экземпляр, в котором несколько автомобилей используют один и тот же физический движок. – Dan Breen 5 December 2013 в 22:19
  • 5
    В этом ответе есть небольшая путаница. ForeignKey не является одним-ко-многим, но это отношения «много-к-одному» в соответствии с официальной документацией django: docs.djangoproject.com/en/2.0/ref/models/fields/… – Kutay Demireren 7 January 2018 в 18:36

Лучший и самый эффективный способ узнать новое - увидеть и изучить реальные практические примеры. Предположим на мгновение, что вы хотите создать блог в django, где журналисты могут писать и публиковать новостные статьи. Владелец интернет-газеты хочет разрешить каждому из своих репортеров публиковать как можно больше статей, но не хочет, чтобы разные журналисты работали над одной и той же статьей. Это означает, что когда читатели идут и читают статью, в статье будет только один автор.

Например: Статья Джона, статья Гарри, статья Рика. Вы не можете иметь статью от Harry & amp; Рик, потому что босс не хочет, чтобы два или более автора работали над одной и той же статьей.

Как мы можем решить эту «проблему» с помощью django? Ключом к решению этой проблемы является django ForeignKey.

Ниже приведен полный код, который можно использовать для реализации идеи нашего босса.

from django.db import models

# Create your models here.

class Reporter(models.Model):
    first_name = models.CharField(max_length=30)

    def __unicode__(self):
        return self.first_name


class Article(models.Model):
    title = models.CharField(max_length=100)
    reporter = models.ForeignKey(Reporter)

    def __unicode__(self):
        return self.title

Запустите python manage.py syncdb, чтобы выполнить код sql и создать таблицы для вашего приложения в своей базе данных. Затем используйте python manage.py shell, чтобы открыть оболочку python.

Создайте объект Reporter R1.

In [49]: from thepub.models import Reporter, Article

In [50]: R1 = Reporter(first_name='Rick')

In [51]: R1.save()

Создайте объект статьи A1.

In [5]: A1 = Article.objects.create(title='TDD In Django', reporter=R1)

In [6]: A1.save()

Затем используйте следующий фрагмент кода, чтобы получить имя репортера.

In [8]: A1.reporter.first_name
Out[8]: 'Rick'

Теперь создайте объект Reporter R2, запустив следующий код python.

In [9]: R2 = Reporter.objects.create(first_name='Harry')

In [10]: R2.save()

Теперь попробуйте добавить R2 в объект статьи A1.

In [13]: A1.reporter.add(R2)

Это не работает, и вы получите AttributeError, говорящий, что объект «Репортер» не имеет атрибута «Добавить».

Как вы может видеть, что объект Article не может быть связан с более чем одним объектом Репортера.

Что относительно R1? Можем ли мы присоединить к нему более одного объекта статьи?

In [14]: A2 = Article.objects.create(title='Python News', reporter=R1)

In [15]: R1.article_set.all()
Out[15]: [<Article: Python News>, <Article: TDD In Django>]

Этот практический пример показывает нам, что django ForeignKey используется для определения отношений «один-к-одному».

OneToOneField используется для создания отношений один к одному.

Мы можем использовать reporter = models.OneToOneField(Reporter) в вышеуказанном файле models.py, но он не будет полезен в наш пример как автора не сможет опубликовать более одной статьи.

Каждый раз, когда вы хотите опубликовать новую статью, вам придется создать новый объект Reporter. Это много времени, не так ли?

Я настоятельно рекомендую попробовать пример с OneToOneField и понять разницу. Я уверен, что после этого примера вы полностью узнаете разницу между django OneToOneField и django ForeignKey.

19
ответ дан 15 August 2018 в 15:34

Также OneToOneField полезно использовать в качестве первичного ключа, чтобы избежать дублирования ключей. Можно использовать неявный / явный autofield

models.AutoField(primary_key=True)

, но вместо этого использовать OneToOneField в качестве первичного ключа (например, модель UserProfile):

user = models.OneToOneField(
    User, null=False, primary_key=True, verbose_name='Member profile')
0
ответ дан 15 August 2018 в 15:34

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

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

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

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

С запросами полей 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.

1
ответ дан 15 August 2018 в 15:34

Другие вопросы по тегам:

Похожие вопросы: