Django_ CreateView показывает наличие класса

У меня есть проект тренажерного зала на django, с booking_create (CreateView) для создания заказов на занятия в тренажерном зале. Я использую модель и форму, с типами пользователей и классов. В HTML-шаблоне есть форма для бронирования занятий. Я хочу сделать эту форму недоступной, когда класс полностью забронирован, показывая вместо этого предупреждающее сообщение.

Мои мысли: Я должен иметь счетчик бронирований для созданных бронирований (например, booking_count), пересчитать это значение к вместимости класса и сохранить это в переменной (например, av_places= class_capacity-booking_count) и если av_places больше нуля, показать форму для регистрации, иначе показать предупреждение. Не уверен, как добавить эту функциональность в представление класса

Ниже представлены классы model, view и template.

models.py:

class Class_Book (models.Model):
    user= models.ForeignKey(User, on_delete=models.CASCADE, null=True, blank=True)
    class = models.ForeignKey(Class, on_delete=models.CASCADE,default= '')
    def __str__(self):
        return f'{self.class}'

views.py

class booking_create (LoginRequiredMixin,CreateView):
    form_class= Booking_Form 
    template_name= ‘booking_create.html'
    success_url=reverse_lazy('home')

template:

 <form method="POST" enctype="multipart/form-data">
     {% csrf_token %}

     {{ form.as_p }}
  <button class="btn btn-success" type="submit">SAVE</button>
  </form>

Вы хотите сделать так, чтобы, если класс полностью забронирован, люди не могли видеть форму бронирования. Вместо этого они увидят сообщение о том, что класс заполнен. Этого можно добиться, добавив некоторую логику в представление.

Сначала настроим модели Ваша модель Booking выглядит хорошо, но есть небольшое замечание:

from django.db import models
from django.contrib.auth.models import User

class Booking(models.Model):
    # It's fine to allow null=True, but usually, you’d want every booking to be tied to a user. 
    # You can automatically set the user in the view, so you might
    # not need null=True unless there's a specific reason.
    user = models.ForeignKey(
        User, on_delete=models.CASCADE, blank=True
    )
    klass = models.ForeignKey(Class, on_delete=models.CASCADE)
    # Just a heads up that default="" isn’t valid for ForeignKey fields, so it’s best to remove that.

    def __str__(self):
        return f"{self.klass}"

Добавление логики бронирования в представление

Теперь давайте добавим в ваше представление логику для проверки того, заполнен ли класс. Для этого мы переопределим метод get в вашем BookingCreateView:

from django.http import HttpResponse
from django.shortcuts import redirect
from django.urls import reverse, reverse_lazy
from django.views.generic import CreateView
from django.contrib.auth.mixins import LoginRequiredMixin

class BookingCreateView(LoginRequiredMixin, CreateView):
    form_class = BookingForm
    template_name = "booking_create.html"
    success_url = reverse_lazy("home")

    # Override the get method to check for availability
    def get(self, request, *args, **kwargs) -> HttpResponse:
        klass_id = self.kwargs.get('klass_id')
        klass = Class.objects.get(id=klass_id)
        
        # Count how many bookings already exist for this class
        booking_count = Booking.objects.filter(klass=klass).count()
        
        # Check if the class is full
        if booking_count >= klass.capacity:  # Assuming 'capacity' is a field in your Class model
            return redirect(reverse("booking_closed"))  # Redirect to a 'booking closed' page
        
        # If there's space, show the form
        return super().get(request, *args, **kwargs)
    def form_valid(self, form: BookingForm):
        # Inject the user to the form before saving.
        booking: Booking = form.instance
        booking.user = self.request.user        
        response = super().form_valid(form)#form save happens here
        return response

Вам нужно создать простую страницу, которая сообщает пользователям, что класс полностью забронирован. Вот как это можно сделать с помощью представления на основе классов (CBV) или представления на основе функций (FBV).

from django.views.generic import TemplateView

class BookingClosedView(TemplateView):
    template_name = "booking_closed.html"

Использование функционально-ориентированного представления (FBV):

from django.shortcuts import render

def booking_closed_view(request):
    return render(request, "booking_closed.html")

Не забудьте добавить шаблон URL для этого в ваш urls.py:

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