[django] django OneToOneField와 ForeignKey의 차이점은 무엇입니까?

장고 OneToOneField와 의 차이점은 무엇입니까 ForeignKey?



답변

OneToOneField(SomeModel)와 사이에 약간의 차이가 있음을주의하십시오 ForeignKey(SomeModel, unique=True). 장고대한 결정적인 가이드에 명시된 바와 같이 :

OneToOneField

일대일 관계. 개념적으로 이것은 ForeignKeywith와 비슷 unique=True하지만 관계의 “역”면이 단일 객체를 직접 반환합니다.

OneToOneField“역방향”관계 와 달리 ForeignKey“역방향”관계는을 반환합니다 QuerySet.

예를 들어 다음 두 가지 모델이있는 경우 (아래의 전체 모델 코드) :

  1. Car 모델 용도 OneToOneField(Engine)
  2. Car2 모델 용도 ForeignKey(Engine2, unique=True)

내부 python manage.py shell에서 다음을 실행하십시오.

OneToOneField

>>> from testapp.models import Car, Engine
>>> c = Car.objects.get(name='Audi')
>>> e = Engine.objects.get(name='Diesel')
>>> e.car
<Car: Audi>

ForeignKeyunique=True

>>> from testapp.models import Car2, Engine2
>>> c2 = Car2.objects.get(name='Mazda')
>>> e2 = Engine2.objects.get(name='Wankel')
>>> e2.car2_set.all()
[<Car2: Mazda>]

모델 코드

from django.db import models

class Engine(models.Model):
    name = models.CharField(max_length=25)

    def __unicode__(self):
        return self.name

class Car(models.Model):
    name = models.CharField(max_length=25)
    engine = models.OneToOneField(Engine)

    def __unicode__(self):
        return self.name

class Engine2(models.Model):
    name = models.CharField(max_length=25)

    def __unicode__(self):
        return self.name

class Car2(models.Model):
    name = models.CharField(max_length=25)
    engine = models.ForeignKey(Engine2, unique=True, on_delete=models.CASCADE)

    def __unicode__(self):
        return self.name


답변

ForeignKey는 일대 다용이므로 Car 객체에는 여러 개의 Wheel이있을 수 있으며 각 Wheel에는 해당 Wheel에 대한 ForeignKey가 있습니다. OneToOneField는 Car 객체가 하나만 가질 수있는 Engine과 같습니다.


답변

새로운 것을 배우는 가장 효과적이고 효과적인 방법은 실제 실제 사례를보고 연구하는 것입니다. 기자가 뉴스 기사를 쓰고 게시 할 수있는 django에서 블로그를 작성하려고한다고 가정하십시오. 온라인 신문의 소유자는 자신의 각 기자가 원하는만큼 많은 기사를 게시 할 수 있기를 원하지만 다른 기사가 동일한 기사를 작성하는 것을 원하지 않습니다. 이는 독자가 기사를 읽고 읽을 때 기사에서 한 명의 작성자 만 선택한다는 것을 의미합니다.

예 : John의 기사, Harry의 기사, Rick의 기사. 상사는 두 명 이상의 저자가 같은 기사를 작업하기를 원하지 않기 때문에 Harry & Rick의 기사를 가질 수 없습니다.

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 syncdbSQL 코드를 실행하고 데이터베이스에 앱 테이블을 구축 할 수 있습니다. 그런 다음 python manage.py shell파이썬 쉘을 열 때 사용하십시오 .

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를 작성하십시오.

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

In [10]: R2.save()

이제 Article 객체 A1에 R2를 추가하십시오.

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

작동하지 않으며 ‘Reporter’개체에 ‘add’속성이 없다고 말하는 AttributeError가 발생합니다.

보시다시피 기사 개체는 둘 이상의 Reporter 개체와 관련 될 수 없습니다.

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>]

이 실제 예는 장고 ForeignKey가 다 대일 관계를 정의하는 데 사용됨을 보여줍니다 .

OneToOneField 일대일 관계를 만드는 데 사용됩니다.

reporter = models.OneToOneField(Reporter)위의 models.py 파일에서 사용할 수 있지만 작성자가 두 개 이상의 기사를 게시 할 수 없으므로이 예에서는 유용하지 않습니다.

새 기사를 게시 할 때마다 새 Reporter 개체를 만들어야합니다. 이것은 시간이 걸리지 않습니까?

나는 함께 예제를 시도 OneToOneField하고 차이점을 깨닫는 것이 좋습니다 . 이 예제를 마치면 django OneToOneField와 django 의 차이점을 완전히 알게 될 것 ForeignKey입니다.


답변

OneToOneField (일대일)는 객체 지향에서 컴포지션의 개념을 인식하는 반면 ForeignKey (일대 다)는 집계와 관련됩니다.


답변

또한 OneToOneField키 중복을 피하기 위해 기본 키로 사용하기에 유용하다. 암시 적 / 명시 적 자동 필드가 없을 수 있습니다

models.AutoField(primary_key=True)

하지만 사용 OneToOneField하는 대신 기본 키는 (상상 UserProfile예를 들어 모델) :

user = models.OneToOneField(
    User, null=False, primary_key=True, verbose_name='Member profile')


답변

OneToOneField에 액세스하면 쿼리 한 필드의 값을 얻습니다. 이 예에서 책 모델의 ‘제목’필드는 OneToOneField입니다.

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

ForeignKey에 액세스하면 관련 모델 개체가 생성되어 추가 쿼리를 수행 할 수 있습니다. 이 예에서 동일한 책 모델의 ‘게시자’필드는 ForeignKey입니다 (게시자 클래스 모델 정의와 관련됨).

>>> 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에 소문자 모델 이름을 추가하여 생성됩니다.


답변

OneToOneField : 두 번째 테이블이 관련된 경우

table2_col1 = models.OneToOneField(table1,on_delete=models.CASCADE, related_name='table1_id')

table2는 table1의 pk 값에 해당하는 하나의 레코드 만 포함합니다. 즉 table2_col1은 table의 pk와 동일한 고유 값을 갖습니다.

table2_col1 == models.ForeignKey(table1, on_delete=models.CASCADE, related_name='table1_id')

table2는 table1의 pk 값에 해당하는 둘 이상의 레코드를 포함 할 수 있습니다.