본문 바로가기
Web developer/Django

[Django] ORM #2

by doongjun 2020. 11. 9.

이번 포스팅에서는 장고에서 ORM 관계 대해 다룰 것이다.

이전 ORM #1 포스팅 참고

2020/11/06 - [Python/Django] - [Django] ORM #1

 

[Django] ORM #1

노마드코더의 강의를 듣고 중요한 내용을 정리하였습니다. ORM ORM은 각 언어별로 있는 기능이다. 원래 데이터베이스 서버의 어떤 데이터를 검색, 추가, 수정, 삭제 등을 할때 SQL을 사용해야 한다.

doongjun.tistory.com

데이터베이스에서 테이블간의 관계를 설정할 때 세가지 옵션이 있다.

 - 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

댓글