Django project # 4

minch·2021년 8월 22일
0

Django

목록 보기
16/16
post-thumbnail

날짜별 예약가능한 방

from django.db   import models

class Book(models.Model):
    user        = models.ForeignKey('users.User', on_delete = models.CASCADE)
    room        = models.ForeignKey('stays.Room', on_delete = models.CASCADE)
    check_in    = models.DateField()
    check_out   = models.DateField()
    
...
    
class Room(models.Model):
    staytype  = models.ForeignKey('Staytype', on_delete = models.PROTECT)
    name      = models.CharField(max_length = 45)
    quantity  = models.IntegerField()

먼저 호텔 페이지에서 체크인 날짜와 체크아웃 날짜를 받아서

해당 기간동안에 객실 예약이 가능한지 여부에 대해서 로직을 구현하였다.

>>> from django.db.models import Sum, Count, F, Q
>>> from stays.models import Room
>>> from books.models import Book
>>> from datetime     import date
>>> CheckIn = date(2021,8,1)
>>> CheckOut = date(2021,8,4)
>>> q1 = Q(book__check_in__gte=CheckIn) & Q(book__check_in__lte=CheckOut)
>>> q2 = Q(book__check_out__gte=CheckIn) & Q(book__check_out__lte=CheckOut)
>>> q3 = Q(book__check_in__lt=CheckIn,book__check_out__gt=CheckOut)
>>> rooms = Room.objects.annotate(
		remain = F('quantity') - Count('book__id',filter=(q1|q2|q3)))

3가지 조건 중 하나라도 만족하는 예약에 대해서 Count 하도록 필터링 해주었다.

잔여 방 개수를 표기하는 remain이라는 column을 추가하고,
remain이 0이 되면 예약이 불가능하게 처리하였다.

Case 사용

이때 해당하는 조건에서 사용할 수 있는 query method가 있는데,

바로 Case이다.

CaseWhen과 같이 쓰이는데,
queryset에서 조건을 추가하여 annotate를 생성할때 쓸 수 있다.

if, elif, else와 같은 조건식을 사용하는 것과 비슷하다.

Case에서 When 안에 조건을 설정해놓고 그 조건을 만족하면,
then을 반환하고, 아니라면 default값을 반환하게 된다.

예를 들어,

>>> rooms = Room.objects.annotate(
		remain 	     = F('quantity') - Count('book__id',filter=(q1|q2|q3)),
        	is_available = Case(
            		When('remain' = 0,
                    	      then    = False),
                              default = True))

위와 같이 코드를 작성하게 되면,

remain의 값이 0일때는 is_available에 False가 반환되고, 아닐땐 True가 반환됩니다.

1개의 댓글

comment-user-thumbnail
2021년 8월 22일

참고해서 데이터 다르게 보냅니다~

답글 달기