Django 모델의 Unique 데이터 만들기

Marco Kang·2021년 1월 9일
6

Django

목록 보기
1/6
post-thumbnail

방을 예약하는 장고 앱을 만든다고 가정하고 예약 모델(Reservation)에 대해 정의하려고 할 때, 각 방에서 한 날짜에 대해 하나의 예약만을 만들어야 한다는 가정을 합니다.
(사실 그게 상식적이지)

(1) 하나의 필드만을 Unique로 만들 경우

위와 같이 reserve_date(예약날짜)에 대해 unique=True를 추가함으로써 복수의 예약에서 같은 날짜의 것이 존재할 수 없도록 합니다.
유저가 두 명 있다고 가정하고(간단하게 user1과 user2)
위와 같이 2020년 1월 9일에 대한 예약 오브젝트를 하나 만듭니다.(2021년이라고 해야 되는데 잘못 친 건 안비밀)
첫번째 오브젝트는 정상적으로 만들어져서 <Reservation: Reservation object (3)>이라는 문구가 뜹니다.

그리고 똑같은 날짜에 또 예약을 만들려고 하면 위와 같이 Traceback 이라면서 에러가 납니다.

reserve_date 필드에 대해 유니크 강제(?)를 실패했다며 IntegrityError가 뜹니다.
이로써 모델에서 유니크한 필드를 정의할 수 있으니 views에서 IntegrityError에 대한 처리를 해 주면 되겠죠.

(2) 복수의 필드를 묶어서 Unique로 만들 경우.
사실 이게 핵심입니다.
일반 SQL을 사용할 때도 그렇지만 복수의 키를 묶어서 Unique 집합으로 만드는 건 굉장히 자주 있는 일일 겁니다. 이걸 Django 모델 안에서도 정의가 가능합니다.

이렇게 class Meta 안에서 constraints를 리스트로써 정의하고 그 안에서 models.UniqueConstraint로 fields에 묶어서 Unique화 할 필드를 리스트로 적어줍니다.
이 경우 user와 reserve_date를 묶어서 넣었습니다.
즉, 한 유저는 하나의 날짜에 대해 복수의 예약을 할 수 없습니다.

미리 user1의 2021년 1월 9일의 예약이 하나만 있다고 가정하겠습니다.
여기에다 한 번 더 2021년 1월 9일에 user1의 예약을 또 넣고보려고 하면 아래와 같은 에러가 나타납니다.


이번에도 위의 (1)처럼 IntegrityError이긴 한데 이번엔 필드가 user_id,reserve_date의 두 가지가 표시됩니다.
즉, 한 유저가 한 날짜에 두 개 이상의 예약을 하려고 하니 에러가 났습니다.

그러면 user2를 user로 한 똑같은 2021년 1월 9일의 예약 생성은 어떻게 될까요?

이 때는 위의 (1)처럼 reserve_date에 넣은 unique=True로 인해 reserve_date가 겹쳤다는 IntegrityError만 발생합니다.


user2로 2021년 1월 10일의 예약은 잘 됩니다.

이렇게 함으로써 기존에 존재하는 데이터와 유저, 날짜 모두 겹치지만 않는다면 하나의 날짜에 대해 한 유저가 선점해서 예약을 할 수 있게 되는(?) 모델을 정의할 수 있게 됩니다.

(reserve_date 필드에 대해 복수의 유니크 정의가 들어간 것이 좋냐 나쁘냐의 이야기는 여기서 하지 않겠습니다.)

profile
데이터 사이언티스트를 향해.

1개의 댓글

comment-user-thumbnail
2022년 12월 19일

딱 찾고 있던 내용이었는데 감사합니다!

답글 달기