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

如何在Django中实现基于日期联动的时段选择系统?

Django实现日期联动加载时段选项的落地方案

一、先修正基础逻辑的错误

你提供的代码里有个小bug:user_date.weekday == 6少了调用括号,应该写成user_date.weekday()。另外用in判断更简洁,修正后的基础逻辑代码:

from datetime import date   

# 符合Django整数选择要求的元组定义
timeslot_weekday = (
    (0, '9:00 - 10:00'),
    (1, '10:00 - 11:00')
)

timeslot_weekend = (
    (0, '10:00 - 11:00'),
    (1, '11:00 - 12:00')
)

user_date = date(2023,1,15)

# weekday()返回0=周一,5=周六,6=周日
if user_date.weekday() in (5, 6):
    print(timeslot_weekend)
else:
    print(timeslot_weekday)

二、Django项目落地步骤

下面分模型、表单、前后端联动三个核心部分实现「选日期后加载对应时段」的需求:

1. 模型设计

如果需要存储用户的预约记录,模型不用固定timeslot的choices(因为要动态切换),可以加一个方法用来获取对应日期的有效时段:

from django.db import models
from datetime import date
from django.core.exceptions import ValidationError

class Booking(models.Model):
    booking_date = models.DateField(verbose_name="预约日期")
    timeslot = models.IntegerField(verbose_name="预约时段")

    def get_available_timeslots(self):
        """根据当前预约日期返回对应时段选项"""
        if self.booking_date.weekday() in (5, 6):
            return timeslot_weekend
        else:
            return timeslot_weekday

    def clean(self):
        """后端验证:确保时段与日期匹配,防止前端篡改"""
        super().clean()
        valid_keys = [key for key, _ in self.get_available_timeslots()]
        if self.timeslot not in valid_keys:
            raise ValidationError(f"所选时段不符合{self.booking_date}的可用规则")

2. 表单与前后端联动(推荐AJAX方式)

要实现用户选完日期后自动加载对应时段,最流畅的方式是前端通过AJAX请求后端获取时段选项,再更新下拉框。

后端视图(提供时段接口)

from django.http import JsonResponse
from django.views.decorators.http import require_GET
from datetime import date

@require_GET
def get_timeslots(request):
    date_str = request.GET.get("date")
    if not date_str:
        return JsonResponse({"error": "请选择日期"}, status=400)
    
    try:
        selected_date = date.fromisoformat(date_str)
    except ValueError:
        return JsonResponse({"error": "日期格式错误"}, status=400)
    
    # 返回对应时段
    if selected_date.weekday() in (5, 6):
        timeslots = timeslot_weekend
    else:
        timeslots = timeslot_weekday
    
    return JsonResponse({"timeslots": timeslots})

前端模板(实现联动逻辑)

用jQuery示例,你也可以用原生JS或Vue等框架实现:

<form id="booking-form" method="post">
    {% csrf_token %}
    <div>
        <label for="booking_date">选择日期:</label>
        <input type="date" id="booking_date" name="booking_date" required>
    </div>
    <div>
        <label for="timeslot">选择时段:</label>
        <select id="timeslot" name="timeslot" disabled>
            <option value="">请先选择日期</option>
        </select>
    </div>
    <button type="submit" disabled>提交预约</button>
</form>

<script src="https://code.jquery.com/jquery-3.6.4.min.js"></script>
<script>
$(document).ready(function() {
    const $dateInput = $("#booking_date");
    const $timeslotSelect = $("#timeslot");
    const $submitBtn = $("button[type='submit']");

    $dateInput.change(function() {
        const selectedDate = $(this).val();
        if (!selectedDate) {
            $timeslotSelect.empty().append("<option value=''>请先选择日期</option>").prop("disabled", true);
            $submitBtn.prop("disabled", true);
            return;
        }

        // 请求后端获取时段
        $.get("/get-timeslots/", {date: selectedDate}, function(data) {
            $timeslotSelect.empty().prop("disabled", false);
            $.each(data.timeslots, function(index, option) {
                $timeslotSelect.append(`<option value="${option[0]}">${option[1]}</option>`);
            });
            $submitBtn.prop("disabled", false);
        }).fail(function() {
            $timeslotSelect.empty().append("<option value=''>加载时段失败</option>").prop("disabled", true);
            $submitBtn.prop("disabled", true);
        });
    });
});
</script>

3. 后端渲染场景的表单处理(可选)

如果是后端直接渲染表单且已知初始日期(比如通过URL参数传递),可以在表单初始化时动态设置timeslot的choices:

from django import forms
from .models import Booking

class BookingForm(forms.ModelForm):
    class Meta:
        model = Booking
        fields = ["booking_date", "timeslot"]

    def __init__(self, *args, **kwargs):
        initial_date = kwargs.pop("initial_date", None)
        super().__init__(*args, **kwargs)

        if initial_date:
            # 根据初始日期设置时段选项
            if initial_date.weekday() in (5, 6):
                self.fields["timeslot"].choices = timeslot_weekend
            else:
                self.fields["timeslot"].choices = timeslot_weekday
        else:
            # 默认禁用时段选择
            self.fields["timeslot"].choices = [("", "请先选择日期")]
            self.fields["timeslot"].widget.attrs["disabled"] = True

在视图中使用这个表单:

from django.shortcuts import render
from .forms import BookingForm
from datetime import date

def create_booking(request):
    initial_date = None
    if request.GET.get("date"):
        try:
            initial_date = date.fromisoformat(request.GET.get("date"))
        except ValueError:
            pass
    
    form = BookingForm(initial_date=initial_date)
    return render(request, "booking/create.html", {"form": form})

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 14:55:06