You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django中基于CreateView实现健身课程满员时隐藏预订表单

解决Django健身课程满员时隐藏预订表单的问题

需求说明

基于Django开发的健身项目,使用booking_create(CreateView)创建健身课程预订记录,当目标课程已被预订满时,隐藏预订表单并显示警告信息。

解决方案步骤

1. 修正模型字段(避免关键字冲突)

原模型中class是Python关键字,需重命名,同时确保Class模型包含课程容量字段:

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

# 课程模型(补充容量字段)
class Class(models.Model):
    name = models.CharField(max_length=100)
    class_capacity = models.IntegerField(default=10)  # 课程最大容纳人数
    # 其他课程相关字段(如时间、地点等)

    def __str__(self):
        return self.name

# 预订记录模型
class Class_Book(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE, null=True, blank=True)
    class_obj = models.ForeignKey(Class, on_delete=models.CASCADE)  # 重命名class为class_obj,避免关键字冲突
    # 其他预订相关字段

    def __str__(self):
        return f'{self.class_obj}'

2. 修改视图类,传递剩余名额到模板并添加提交校验

在booking_create视图中重写get_context_data方法计算剩余名额,同时在表单提交时再次校验,防止并发超订:

# views.py
from django.views.generic.edit import CreateView
from django.contrib.auth.mixins import LoginRequiredMixin
from django.urls import reverse_lazy
from .models import Class_Book, Class
from .forms import Booking_Form

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

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        # 从URL参数获取当前课程ID(假设URL配置为 /booking/create/<int:pk>/)
        class_id = self.kwargs.get('pk')
        current_class = Class.objects.get(pk=class_id)
        # 统计已预订人数
        booked_count = Class_Book.objects.filter(class_obj=current_class).count()
        # 计算剩余名额并传入模板
        context['remaining_places'] = current_class.class_capacity - booked_count
        context['current_course'] = current_class
        return context

    # 提交表单时再次校验,避免并发导致超订
    def form_valid(self, form):
        class_id = self.kwargs.get('pk')
        current_class = Class.objects.get(pk=class_id)
        booked_count = Class_Book.objects.filter(class_obj=current_class).count()
        
        if current_class.class_capacity - booked_count <= 0:
            form.add_error(None, "该课程已预订满,无法提交预订")
            return self.form_invalid(form)
        
        # 关联当前用户到预订记录(如果表单未自动处理)
        form.instance.user = self.request.user
        return super().form_valid(form)

3. 修改模板,根据剩余名额显示内容

在模板中根据remaining_places的值判断显示表单还是警告信息:

<!-- booking_create.html -->
{% if remaining_places > 0 %}
    <div class="alert alert-info">
        当前课程:{{ current_course.name }},剩余名额:{{ remaining_places }}
    </div>
    <form method="POST" enctype="multipart/form-data">
        {% csrf_token %}
        {{ form.as_p }}
        <button class="btn btn-success" type="submit">确认预订</button>
    </form>
{% else %}
    <div class="alert alert-danger">
        抱歉,{{ current_course.name }}课程已全部预订满,无法继续报名!
    </div>
{% endif %}

<!-- 显示表单错误信息(包括提交时的满员校验错误) -->
{% if form.errors %}
    {% for error in form.non_field_errors %}
        <div class="alert alert-danger mt-3">{{ error }}</div>
    {% endfor %}
{% endif %}

注意事项

  • 确保URL配置传递课程ID,例如:path('booking/create/<int:pk>/', booking_create.as_view(), name='booking_create')
  • 如果你的Booking_Form已经自动关联用户和课程,可调整视图中的逻辑,避免重复赋值
  • 高并发场景下,建议使用数据库事务或F表达式进一步优化,防止超订

内容的提问来源于stack exchange,提问作者maria

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 16:25:03