스타벅스 모델링을 하다가 Product 와 Nutrition의 one-to-one 관계를 one-to-many와 똑같이 ForeignKey를 사용하여 나타내면 되는줄 알고 처음엔 똑같은 방식으로 둘의 관계를 연결하였다.
하지만, one-to-one 관계를 나타내는 필드는OneToOneField
였던것! 🤷♀️
OneToOneField 방법과 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.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를 사용하여 둘의 관계를 나타낼 때
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설정