이번 포스팅에서는 장고에서 ORM 관계 대해 다룰 것이다.
이전 ORM #1 포스팅 참고
2020/11/06 - [Python/Django] - [Django] ORM #1
데이터베이스에서 테이블간의 관계를 설정할 때 세가지 옵션이 있다.
- One to One
- Many to One
- Many to Many
One to One 관계란 어느 객체에서 다른 객체를 보더라도 반드시 단 하나씩 관계를 가지는 것을 말한다. 예를 들어 일부일처제 결혼제도에서 법적으로 한 남자는 한 여자와, 한 여자는 한 남자와 결혼할 수밖에 없다. 즉 남편은 부인을 두명이상 둘 수 없다. 이러한 관계를 1:1관계라고 한다.
Many to One 관계란 한쪽 객체가 관계를 맺은 객체 쪽의 여러 객체를 가질 수 있는 것을 의미한다. 예를 들어 엄마는 자식을 여러명 가질 수 있지만 자식은 엄마가 여러명이 있을 수는 없다. 이러한 관계를 n:1관계라고 한다.
Many to Many 관계란 관계를 가진 양쪽 객체 모두에서 n:1관계가 존재할 때 나타나는 모습이다. 즉 서로가 서로를 n:1관계로 본다. 예를 들어 1,2,3형제가 있을 때, 2는 1을 형으로 두고 3도 형으로 둘 수 있다. 반대로 1도 2와 3을 동생으로 둘 수있다. 이러한 관계를 n:m관계라고 한다.
장고 ORM에서 모델간의 Many to One, Many to Many 관계를 설정해 주고 싶다면 어떻게 해야할까?
아래 코드를 살펴보자
from django.db import models
from django_countries.fields import CountryField
from core import models as core_models
class AbstractItem(core_models.TimeStampedModel):
""" Abstract Item """
name = models.CharField(max_length=80)
class Meta:
abstract = True
def __str__(self):
return self.name
class RoomType(AbstractItem):
""" RoomType Model Definition """
class Meta:
verbose_name = "Room Type"
ordering = ["created"] # 생성 순으로 정렬
class Amenity(AbstractItem):
""" Amenity Object Definition """
class Meta:
verbose_name_plural = "Amenities" # Amenitys 철자 오류 방지
class Facility(AbstractItem):
""" Facility Model Definition """
class Meta:
verbose_name_plural = "Facilities"
class HouseRule(AbstractItem):
""" HouseRule Model Definition """
class Meta:
verbose_name = "House Rule"
class Photo(core_models.TimeStampedModel):
""" Photo Model Definition """
caption = models.CharField(max_length=80)
file = models.ImageField()
room = models.ForeignKey("Room", related_name="photos", on_delete=models.CASCADE)
def __str__(self):
return self.caption
class Room(core_models.TimeStampedModel):
""" Room Model Definition """
name = models.CharField(max_length=140)
description = models.TextField()
country = CountryField()
city = models.CharField(max_length=80)
price = models.IntegerField()
address = models.CharField(max_length=140)
guests = models.IntegerField()
beds = models.IntegerField()
bedrooms = models.IntegerField()
baths = models.IntegerField()
check_in = models.TimeField()
check_out = models.TimeField()
instant_book = models.BooleanField(default=False)
host = models.ForeignKey(
"users.User", related_name="rooms", on_delete=models.CASCADE
)
room_type = models.ForeignKey(
"RoomType", related_name="rooms", on_delete=models.SET_NULL, null=True
)
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)
def __str__(self):
return self.name
위 부분에서 다른 앱의 모델과 다른 클래스의 모델을 ForeignKey를 이용해 Many to One 관계를 설정 해 준 것이다.
host = models.ForeignKey(
"users.User", related_name="rooms", on_delete=models.CASCADE
)
room_type = models.ForeignKey(
"RoomType", related_name="rooms", on_delete=models.SET_NULL, null=True
)
게스트하우스 예약 웹페이지를 구현할 때, 집 주인과 그 집주인이 올린 방은 연결되어야 할 것이다. 또, 집 주인은 방을 여러개 올릴 수 있지만 방은 주인이 여러명일 수는 없다.
host는 이전 포스팅(ORM #1)에서 설정해주었던 users어플리케이션의 User모델과의 관계, room_type은 RoomType모델과의 관계설정을 해준 것이다. 이때, User와 RoomType에서도 _set을 사용해 Room의 객체를 사용할 수 있다.
related_name="rooms" 는 "room_set"을 "rooms"로 변경 즉 대상을 찾는 방식을 변경한 것이다. 이 것은 다음 포스팅에서 활용해 볼 예정이다.
on_delete=models.CASCADE 는 user가 삭제되면 그 room도 삭제된다는 설정을 해준 것이다. 더 다양한 설정이 많은데 이는 docs.djangoproject.com/en/3.1/ref/models/fields/ 링크에서 더 많이 참고할 수 있다.
또, Many to Many 관계는 ManytoManyField()를 이용해 아래와 같이 설정 해 준 것이다.
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)
방은 각종 용품과 소모품, 시설, 규칙을 여러 개 가질 수 있고, Amenity, Facility, HouseRule도 여러 개의 방에 있을 수 것이다. amenities, facilities, house_rules는 Amenity, Facility, HouseRule 모델과의 관계 설정이 된 것을 아래와 같이 확인할 수 있다.
'Web developer > Django' 카테고리의 다른 글
[Django] 장고 템플릿 #1 (0) | 2020.11.13 |
---|---|
[Django] 쿼리셋(Query sets) (0) | 2020.11.09 |
[Django] 모델 상속 (0) | 2020.11.06 |
[Django] ORM #1 (0) | 2020.11.06 |
[Django] 마이그레이션 (0) | 2020.11.06 |
댓글