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

如何移除已选时段避免重复预订(Django理发预约系统)

解决理发师预订时段重复选择问题

要实现「特定日期下,理发师已被预订的时段从列表中移除」的需求,我们需要从表单动态过滤选项、提交时并发验证、前端实时更新三个层面入手,以下是具体实现方案:

1. 修改表单逻辑,动态生成可选时段

在forms.py中,让表单根据用户选择的日期和理发师自动过滤已预订时段,同时在提交时二次验证防止并发冲突:

from .models import Booking, TIME_SLOTS
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(),
        }

    def __init__(self, *args, **kwargs):
        # 从参数中获取用户已选的日期和理发师(可选)
        self.selected_date = kwargs.pop('selected_date', None)
        self.selected_barber = kwargs.pop('selected_barber', None)
        super().__init__(*args, **kwargs)
        
        # 若有明确的日期和理发师,过滤已预订时段
        if self.selected_date and self.selected_barber:
            # 查询该日期该理发师已被占用的时段
            booked_times = Booking.objects.filter(
                date=self.selected_date,
                barber=self.selected_barber
            ).values_list('time', flat=True)
            # 从预设时段中剔除已占用的选项
            available_times = [slot for slot in TIME_SLOTS if slot[0] not in booked_times]
            self.fields['time'].choices = available_times
        else:
            # 默认显示所有时段
            self.fields['time'].choices = TIME_SLOTS

    def clean(self):
        cleaned_data = super().clean()
        date = cleaned_data.get('date')
        time = cleaned_data.get('time')
        barber = cleaned_data.get('barber')

        # 提交时二次验证,避免多用户并发预订同一时段
        if date and time and barber:
            if Booking.objects.filter(date=date, time=time, barber=barber).exists():
                raise forms.ValidationError(f"时段{time}已被预订,请选择其他时段。")
        return cleaned_data

2. 更新视图,支持动态参数传递

修改views.py,让视图接收日期和理发师的查询参数,初始化表单时传入这些参数,确保表单显示正确的可选时段:

from django.shortcuts import render
from django.contrib.auth.decorators import login_required
from django.contrib import messages
from django.http import HttpResponseRedirect
from .models import Booking
from .forms import BookingForm
from datetime import date

@login_required()
def make_booking(request):
    selected_date = request.GET.get('date')
    selected_barber = request.GET.get('barber')

    # 将前端传来的日期字符串转换为date对象
    if selected_date:
        try:
            selected_date = date.fromisoformat(selected_date)
        except ValueError:
            selected_date = None

    if request.method == "POST":
        # 提交时传入选中的日期和理发师,确保表单验证时能正确过滤
        form = BookingForm(
            request.POST,
            selected_date=request.POST.get('date'),
            selected_barber=request.POST.get('barber')
        )
        if form.is_valid():
            booking_form = form.save(commit=False)
            booking_form.customer = request.user
            booking_form.save()
            messages.success(request, '您的预订已提交,等待确认')
            return HttpResponseRedirect('/bookings')
    else:
        # GET请求时,根据查询参数初始化表单
        form = BookingForm(
            selected_date=selected_date,
            selected_barber=selected_barber
        )

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

3. 前端实时更新(可选,提升用户体验)

在bookings.html中添加AJAX逻辑,当用户选择日期或理发师后,自动更新时段下拉框,无需刷新页面:

<form method="post" id="booking-form">
    {% csrf_token %}
    {{ form.as_p }}
    <button type="submit">提交预订</button>
</form>

<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script>
$(document).ready(function() {
    // 监听日期和理发师选择框的变化事件
    $('#id_date, #id_barber').change(function() {
        var date = $('#id_date').val();
        var barber = $('#id_barber').val();
        
        // 发送GET请求获取更新后的表单片段
        $.get('{% url "make_booking" %}', {date: date, barber: barber}, function(data) {
            // 替换时段下拉框的选项
            var new_time_options = $(data).find('#id_time').html();
            $('#id_time').html(new_time_options);
        });
    });
});
</script>

4. 补充URL配置

确保在urls.py中给视图命名,让前端的{% url %}标签能正确生成请求地址:

from django.urls import path
from . import views

urlpatterns = [
    path('book/', views.make_booking, name='make_booking'),
    # 其他URL配置...
]

关键逻辑说明

  • 动态过滤时段:表单初始化时根据已选日期和理发师,从数据库查询已预订时段,剔除后生成可选列表
  • 并发验证:提交时再次检查时段是否被占用,避免多个用户同时提交同一时段导致的重复预订
  • 实时更新:通过AJAX实现无刷新更新时段列表,提升用户操作体验

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.23 15:39:21