如何在Django预订表单中移除数据库已存在的时间选项?
Django预订表单动态过滤已占用时间
要实现所选日期下仅显示未被预订的时间选项,可以通过「后端查询可用时间 + 前端AJAX动态更新」的方式实现,以下是具体步骤:
1. 完善表单类(若未定义)
确保你的BookingForm基于ModelForm创建,在forms.py中添加:
from django import forms from .models import Booking, TIME_CHOICES class BookingForm(forms.ModelForm): class Meta: model = Booking fields = ['first_name', 'last_name', 'email_address', 'phone_number', 'date_of_booking', 'time_of_booking', 'number_of_people', 'special_requests']
2. 添加AJAX接口视图
在views.py中新增视图,用于接收日期参数、查询可用时间并返回JSON结果:
from django.http import JsonResponse from .models import Booking, TIME_CHOICES import datetime def get_available_times(request): selected_date = request.GET.get('date') if not selected_date: return JsonResponse({'available_times': []}) # 转换日期格式并查询已预订时间 booking_date = datetime.datetime.strptime(selected_date, '%Y-%m-%d').date() booked_times = Booking.objects.filter(date_of_booking=booking_date).values_list('time_of_booking', flat=True) # 筛选未被占用的时间选项 available_times = [time for time in TIME_CHOICES if time[0] not in booked_times] formatted_times = [{'value': t[0], 'text': t[1]} for t in available_times] return JsonResponse({'available_times': formatted_times})
3. 配置路由
在urls.py中添加AJAX接口的路由:
from django.urls import path from . import views urlpatterns = [ path('make-booking/', views.make_booking, name='make_booking'), path('get-available-times/', views.get_available_times, name='get_available_times'), # 其他已有路由... ]
4. 修改模板实现动态更新
在booking/make_booking.html中添加JavaScript,监听日期选择事件并更新时间下拉框:
<form method="POST"> {% csrf_token %} {{ form.as_p }} <button type="submit">提交预订</button> </form> <script src="https://code.jquery.com/jquery-3.6.4.min.js"></script> <script> $(document).ready(function() { // 页面加载时初始化可用时间 updateTimeOptions($('#id_date_of_booking').val()); // 监听日期选择变化 $('#id_date_of_booking').on('change', function() { updateTimeOptions($(this).val()); }); // 更新时间选项的函数 function updateTimeOptions(date) { $.ajax({ url: "{% url 'get_available_times' %}", data: {'date': date}, dataType: 'json', success: function(res) { const timeSelect = $('#id_time_of_booking'); timeSelect.empty(); res.available_times.forEach(time => { timeSelect.append($('<option>').val(time.value).text(time.text)); }); } }); } }); </script>
可选:静态初始化过滤(非动态)
如果不需要实时更新,可在页面加载时直接根据默认日期过滤时间选项,修改make_booking视图:
def make_booking(request): if request.method == 'POST': form = BookingForm(request.POST) if form.is_valid(): form.save() return redirect(get_bookings) else: target_date = request.GET.get('date') form = BookingForm() if target_date: try: booking_date = datetime.datetime.strptime(target_date, '%Y-%m-%d').date() booked_times = Booking.objects.filter(date_of_booking=booking_date).values_list('time_of_booking', flat=True) available_times = [t for t in TIME_CHOICES if t[0] not in booked_times] form.fields['time_of_booking'].choices = available_times except ValueError: pass context = {'form': form} return render(request, 'booking/make_booking.html', context)
内容的提问来源于stack exchange,提问作者ladcode2022
相关产品推荐
相关产品推荐

