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이 되면 예약이 불가능하게 처리하였다.
이때 해당하는 조건에서 사용할 수 있는 query method가 있는데,
바로 Case
이다.
Case
는 When
과 같이 쓰이는데,
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가 반환됩니다.
참고해서 데이터 다르게 보냅니다~