이어서 onetomany
, manytoone
, manytomany
관계와 ForeignKey
에 대해 알아보겠습니다.
외래키(Foreign Key)
란 테이블의 필드 중에서 다른 테이블의 행과 식별할 수 있는 키를 의미합니다.
다음과 같은 테이블은 너무 많은 열(column)이 추가되어 효율적이지 못한 구조입니다.
너무 많은 열과 데이터로 조회하는데 비교적 오랜시간이 소요될 수 있습니다. 그래서 다음 아래의 사진과 같이 두개의 테이블로 나누고 연결고리를 만들어줍니다.
결론적으로 두 테이블을 연결할 수 있도록 하는 것이 Foreign Key
의 역할입니다.
class Room(core_models.TimeStampedModel):
host = models.ForeignKey(
"users.User", related_name="rooms", on_delete=models.CASCADE, null=True
)
room_type = models.ForeignKey(
"RoomType", related_name="rooms", on_delete=models.SET_NULL, null=True
)
외래키를 작성할 때 필수적으로 포함되어야할 매개변수는 참조할 테이블, 개체 관계에 사용할 이름, 개체 삭제시 수행할 동작 등 입니다.
참조할 테이블은 외래키에서 어떤 테이블을 참조할지 의미합니다. 예제에서는 user 폴더의 User 테이블, RoomType 테이블입니다.
개체 관계에 사용할 이름(related_name)은 추상 모델에서 관계를 정의할 때 사용될 이름을 의미합니다. 예제에서는 rooms입니다.
개체 삭제시 수행할 동작(on_delete)은 외래키(ForeignKey)가 바라보는 테이블의 값이 삭제될 때 수행할 방법을 지정합니다. 예를 들어 유저가 삭제되었을 때 남아있는 방을 지울 것인지, 에러를 띄워 방을 보호할 것인지 등입니다.
이는 자신과 ManyToOne(다대일 관계)
에 해당하는 객체만 적용될 수 있습니다.
다음의 코드는 여러개의 타입을 여러 방에 연결하도록 하는 ManyToMany 필드입니다.
class Amenity(AbstractItem):
class Meta:
verbose_name_plural = "Amenities"
class Facility(AbstractItem):
class Meta:
#abstract = True
verbose_name_plural = "Facilities"
class HouseRule(AbstractItem):
class Meta:
verbose_name = "House Rule"
class Room(core_models.TimeStampedModel):
amenities = models.ManyToManyField("Amenity", related_name="rooms", blank=True)
facilities = models.ManyToManyField("Facility", related_name="rooms", blank=True)
house_rules = models.ManyToManyField("HouseRule", related_name="rooms", blank=True)
이 관계에서 두 모델 중 어느 쪽에서 선언해도 상관없습니다. blank=True
옵션을 걸어준 이유는 하나도 지정안할 수 도 있도록 하기 위함입니다.
추가로 meta class
는 class 안의 class로 verbose_name(복수), ordering 등을 지정할 수 있고, abstract = true해두면 model이지만 데이터베이스에 나타나지 않습니다.
OneToOneField
는 1:1 관계를 의미합니다.
class User(AbstractBaseUser):
# 생략
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
위 코드는 django 에 기본적으로 정의되어 있는 User 모델과 이를 커스튬하여 새로 만드는 Profile 모델을 연결한 모델입니다.