Как удалить уже выбранную опцию из списка опций, чтобы избежать двойного бронирования

Я уже 2 дня ломаю голову над этим вопросом в надежде на внезапное озарение и ни к чему не пришел. Я полностью запутался в своей логике и все попытки привели к тому, что я сломал свой код. Я пытаюсь сделать так, чтобы в определенную дату, если пользователь уже выбрал тайм-слот с выбранным парикмахером, этот тайм-слот был удален из списка тайм-слотов, так что он не может быть выбран снова другим пользователем

Из 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}"

из файла 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})

из файла 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(),
        }

Так или иначе, вам понадобится другое представление, которое будет принимать выбранную дату и возвращать доступные временные интервалы. Если вы хотите сделать это с помощью AJAX, то ваше представление может выглядеть примерно так:

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)

Лучшим способом, по моему мнению, было бы создание новых моделей для тайм-слотов, услуг и парикмахеров. Во-первых, вы не храните информацию в жестком коде и можете динамически изменять ее в БД. Во-вторых, вы можете создать очень простой запрос для получения доступных тайм-слотов на день, парикмахера, услуги и т.д. Вы также можете установить общую доступность, связав определенных парикмахеров с определенными временными интервалами, в зависимости от часов их работы.

Вернуться на верх