Reservations 관련 로직 구현
이번 시간엔 Reservations 관련 기능을 구현해보겠습니다.
1. Reservation Form 구현
먼저, 예약을 위한 Form을 구현해보겠습니다.
# books/forms.py
class ReservationForm(forms.ModelForm):
class Meta:
model = Reservation
fields = [] # user와 book은 view에서 처리
def clean(self):
cleaned_data = super().clean()
user = self.user
book = self.book
# 이미 동일한 도서에 대한 예약이 있는지 확인
existing_reservation = Reservation.objects.filter(
user=user,
book=book,
status='WAITING'
).exists()
if existing_reservation:
raise forms.ValidationError('이미 예약한 도서입니다.')
# 현재 대출 가능한 도서가 있는 경우 예약 불가
if book.is_available():
raise forms.ValidationError('현재 대출 가능한 도서가 있어 예약할 수 없습니다.')
return cleaned_data
def __init__(self, *args, **kwargs):
self.user = kwargs.pop('user', None)
self.book = kwargs.pop('book', None)
super().__init__(*args, **kwargs)
# books/forms.py
class ReservationForm(forms.ModelForm):
class Meta:
model = Reservation
fields = [] # user와 book은 view에서 처리
def clean(self):
cleaned_data = super().clean()
user = self.user
book = self.book
# 이미 동일한 도서에 대한 예약이 있는지 확인
existing_reservation = Reservation.objects.filter(
user=user,
book=book,
status='WAITING'
).exists()
if existing_reservation:
raise forms.ValidationError('이미 예약한 도서입니다.')
# 현재 대출 가능한 도서가 있는 경우 예약 불가
if book.is_available():
raise forms.ValidationError('현재 대출 가능한 도서가 있어 예약할 수 없습니다.')
return cleaned_data
def __init__(self, *args, **kwargs):
self.user = kwargs.pop('user', None)
self.book = kwargs.pop('book', None)
super().__init__(*args, **kwargs)
2. Reservation View 구현
2.1 예약 생성 (도서 예약)
# books/views.py
@login_required # 로그인 여부 확인
def reservation_create(request, book_id):
"""도서 예약"""
book = get_object_or_404(Book, pk=book_id)
if request.method == 'POST': # POST 요청인 경우
form = ReservationForm(request.POST, user=request.user, book=book)
if form.is_valid():
reservation = form.save(commit=False)
reservation.user = request.user
reservation.book = book
reservation.expiry_date = timezone.now() + timedelta(days=1) # 1일간 예약 유효
reservation.save()
messages.success(request, f'{book.title} 도서가 예약되었습니다.')
return redirect('books:reservation-list') # 예약 목록 페이지로 이동
else:
form = ReservationForm(user=request.user, book=book)
return render(request, 'books/reservation_form.html', {
'form': form,
'book': book
})
# books/views.py
@login_required # 로그인 여부 확인
def reservation_create(request, book_id):
"""도서 예약"""
book = get_object_or_404(Book, pk=book_id)
if request.method == 'POST': # POST 요청인 경우
form = ReservationForm(request.POST, user=request.user, book=book)
if form.is_valid():
reservation = form.save(commit=False)
reservation.user = request.user
reservation.book = book
reservation.expiry_date = timezone.now() + timedelta(days=1) # 1일간 예약 유효
reservation.save()
messages.success(request, f'{book.title} 도서가 예약되었습니다.')
return redirect('books:reservation-list') # 예약 목록 페이지로 이동
else:
form = ReservationForm(user=request.user, book=book)
return render(request, 'books/reservation_form.html', {
'form': form,
'book': book
})
2.2 예약 목록 조회
@login_required
def reservation_list(request):
"""예약 목록"""
if request.user.is_librarian(): # 사서인 경우
reservations = Reservation.objects.all().order_by('reserved_date') # 모든 예약 목록 조회
else:
reservations = Reservation.objects.filter(
user=request.user,
status__in=['WAITING', 'AVAILABLE'] # 대기 중, 대출 가능한 예약만 조회
).order_by('reserved_date')
return render(request, 'books/reservation_list.html', {
'reservations': reservations
})
@login_required
def reservation_list(request):
"""예약 목록"""
if request.user.is_librarian(): # 사서인 경우
reservations = Reservation.objects.all().order_by('reserved_date') # 모든 예약 목록 조회
else:
reservations = Reservation.objects.filter(
user=request.user,
status__in=['WAITING', 'AVAILABLE'] # 대기 중, 대출 가능한 예약만 조회
).order_by('reserved_date')
return render(request, 'books/reservation_list.html', {
'reservations': reservations
})
2.3 예약 취소
@login_required
def reservation_cancel(request, reservation_id):
"""예약 취소"""
reservation = get_object_or_404(Reservation, pk=reservation_id)
if request.user != reservation.user and not request.user.is_librarian(): # 본인의 예약이거나 사서만 취소 가능
messages.error(request, '권한이 없습니다.')
return redirect('books:reservation-list')
if request.method == 'POST':
if reservation.status in ['WAITING', 'AVAILABLE']: # 대기 중, 대출 가능한 경우에만 취소 가능
reservation.status = 'CANCELLED' # 예약 취소
reservation.save() # 예약 정보 저장
messages.success(request, '예약이 취소되었습니다.')
return redirect('books:reservation-list') # 예약 목록 페이지로 이동
else:
messages.error(request, '잘못된 접근입니다.')
return redirect('books:reservation-list')
@login_required
def reservation_cancel(request, reservation_id):
"""예약 취소"""
reservation = get_object_or_404(Reservation, pk=reservation_id)
if request.user != reservation.user and not request.user.is_librarian(): # 본인의 예약이거나 사서만 취소 가능
messages.error(request, '권한이 없습니다.')
return redirect('books:reservation-list')
if request.method == 'POST':
if reservation.status in ['WAITING', 'AVAILABLE']: # 대기 중, 대출 가능한 경우에만 취소 가능
reservation.status = 'CANCELLED' # 예약 취소
reservation.save() # 예약 정보 저장
messages.success(request, '예약이 취소되었습니다.')
return redirect('books:reservation-list') # 예약 목록 페이지로 이동
else:
messages.error(request, '잘못된 접근입니다.')
return redirect('books:reservation-list')