Ad

How To Remove An Already Selected Option From Options List To Avoid Double Bookings

I've been scratching my head with this for 2 days hoping for a sudden brainwave and getting nowhere. I've completely drawn a blank with my logic and all attempts have resulted in me breaking my code. I'm trying to get it so that on a specific date, if a user has already selected a time slot with a selected barber, that that time slot will be removed from the list of time slots, so it cannot be selected again by another user.

From models.py

from django.db import models
import datetime
from django.core.validators import MinValueValidator
from django.contrib.auth.models import User

SERVICES = (
        ('Gents Cut', 'Gents Cut'),
        ('Kids Cut', 'Kids Cut'),
        ('Cut and Shave', 'Cut and Shave'),
        ('Shave Only', 'Shave Only'),
        )

TIME_SLOTS = (
        ('9.00 - 10.00', '9.00 - 10.00'),
        ('10.00 - 11.00', '10.00 - 11.00'),
        ('11.00 - 12.00', '11.00 - 12.00'),
        ('12.00 - 13.00', '12.00 - 13.00'),
        ('13.00 - 14.00', '13.00 - 14.00'),
        ('14.00 - 15.00', '14.00 - 15.00'),
        ('15.00 - 16.00', '15.00 - 16.00'),
        ('16.00 - 17.00', '16.00 - 17.00'),
        ('17.00 - 18.00', '17.00 - 18.00'),
        )

BARBER_NAME = (
        ('Nathan', 'Nathan'),
        ('Chris', 'Chris'),
        ('Ben', 'Ben'),
        ('Dan', 'Dan'),
        )


class Booking(models.Model):
    date = models.DateField(validators=[MinValueValidator(datetime.date.today)])
    time = models.CharField(max_length=50, null=True, choices=TIME_SLOTS)
    barber = models.CharField(max_length=50, null=True, choices=BARBER_NAME)
    service = models.CharField(max_length=50, null=True, choices=SERVICES)
    customer = models.ForeignKey(User, on_delete=models.CASCADE)

    def __str__(self):
        return f"{self.customer} has booked {self.service} on {self.date} at {self.time} with {self.barber}"

from views.py

from django.shortcuts import render, get_object_or_404
from django.contrib.auth.decorators import login_required
from django.views import generic, View
from django.contrib import messages
from django.http import HttpResponseRedirect
from .models import Booking
from .forms import BookingForm


@login_required()
def make_booking(request):
    if request.method == "POST":
        form = BookingForm(request.POST)
        if form.is_valid():
            booking_form = form.save(commit=False)
            booking_form.customer = request.user
            booking_form.save()
            messages.success(request, ('Your booking is awaiting confirmation'))
            return HttpResponseRedirect('/bookings')
    else:
        form = BookingForm()

    return render(request, 'bookings.html', {'form': form})

from forms.py

from .models import Booking
import datetime
from django import forms


class DatePicker(forms.DateInput):
    input_type = 'date'


class BookingForm(forms.ModelForm):
    class Meta:
        model = Booking
        fields = ('date', 'time', 'barber', 'service',)
        widgets = {
            'date': DatePicker(),
        }
Ad

Answer

One way or another you will need another view to accept the selected date and return the available time slots. If you were to do this via AJAX then your view might look something like this:

import json
from datetime import datetime

def get_time_slots(request):
    # get the date in python format, sent via ajax request
    date = datetime.strptime(request.GET.get('date'), '%Y-%m-%d')

    # get all times from bookings on the provided date
    booked_slots = Booking.objects.filter(date=date).values_list('time', flat=True)
    
    available_slots = []
    for slots in TIME_SLOTS:
        if slots[0] not in booked_slots:
            available_slots.append(slots)

    times_as_json = json.dumps(available_slots)
    return JsonResponse(times_as_json)

A better way, imo, would be to create new models for time slots, services, and barbers. Firstly, you are not hardcoding information and can dynamically change things in the DB. Secondly, you can generate a very slick query to get the available time slots for a day, barber, service, etc. You can also set general availability by linking certain barbers to certain time slots, depending on the hours they work.

Ad
source: stackoverflow.com
Ad