Django : one-to-one & one-to-many

gaya309·2021년 5월 24일
0

Django

목록 보기
1/3
post-thumbnail

스타벅스 모델링을 하다가 Product 와 Nutrition의 one-to-one 관계를 one-to-many와 똑같이 ForeignKey를 사용하여 나타내면 되는줄 알고 처음엔 똑같은 방식으로 둘의 관계를 연결하였다.
하지만, one-to-one 관계를 나타내는 필드는 OneToOneField 였던것! 🤷‍♀️
OneToOneField 방법과 ForeignKey 방법의 차이를 알아보고자 한다.

OneToOneField

class Product(models.Model):
    category = models.ForeignKey('Category', on_delete = models.CASCADE)
    korean_name = models.CharField(max_length=45)
    english_name = models.CharField(max_length=45)
    description = models.TextField()
    nutrition = models.OneToOneField('Nutrition', on_delete=CASCADE)  

    class Meta:
        db_table = 'products'


class Nutrition(models.Model):
    one_serving_kcal = models.DecimalField(max_digits=6, decimal_places=2, null=True)
    sodium_mg = models.DecimalField(max_digits=6, decimal_places=2, null=True)
    saturated_fat_g = models.DecimalField(max_digits=6, decimal_places=2, null=True)

    class Meta:
        db_table = 'nutritions'

위와 같이 OneToOneField를 사용 할 때

서로 객체를 불러올 때 one-to-one 관계이기 때문에 _set 없어도 연결되어 있는 객체 한 개가 불러와진다.

ForeignKey

하지만!

아래 코드처럼 ForeignKey를 사용하여 둘의 관계를 나타낼 때

class Product(models.Model):
    category = models.ForeignKey('Category', on_delete = models.CASCADE)
    korean_name = models.CharField(max_length=45)
    english_name = models.CharField(max_length=45)
    description = models.TextField()
    nutrition = models.ForeignKey('Nutrition', on_delete=CASCADE)  
    class Meta:
        db_table = 'products'

class Nutrition(models.Model):
    one_serving_kcal = models.DecimalField(max_digits=6, decimal_places=2, null=True)
    sodium_mg = models.DecimalField(max_digits=6, decimal_places=2, null=True)
    saturated_fat_g = models.DecimalField(max_digits=6, decimal_places=2, null=True)

    class Meta:
        db_table = 'nutritions'

위와 같이 foreignkey를 사용하여 두 테이블 관계를 나타낼 경우, nutrition과 product의 관계가 1:다가 됨으로, nutrition에서 product에 바로 접근하는 것이 불가능 해진다.

product에서는 연결된 nutrition 객체 하나를 불러올 수 있지만, nutrition에서는 연결된 product의 객체에 접근하려면 오류가 나게 된다.

➡️ nutrition에 연결되어 있는 product중 어떤것을 가져와야 하는지 모른다!
➡️ _set사용하여 역참조 가능! or related_name설정

🗣 결론

  • ForeignKey를 사용할 경우 one-to-many
  • one-to-one을 관계를 나타낼 때는 OneToOneField를 사용하자!
  • one-to-many일 경우 _set or related_name 설정을 사용하여 역참조 가능
profile
🎓의지적인 삶을 살자!😊

0개의 댓글