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

如何将日期选择器表单数据传递至Django代码(含HTMX方案)

解决方案:获取日期范围并筛选Django数据

首先,你的现有表单仅对应单个expiration_date字段,要实现开始/结束日期范围筛选,需要先调整表单结构,再通过传统Django提交或HTMX两种方式处理数据传递。

一、调整表单(适配日期范围需求)

创建专门用于日期筛选的表单(而非绑定Offer模型的ModelForm),因为你需要的是筛选条件,而非创建/修改Offer实例:

# forms.py
from django import forms

class DateInput(forms.DateInput):
    input_type = 'date'

class DateRangeFilterForm(forms.Form):
    start_date = forms.DateField(
        label='开始日期',
        required=False,
        widget=DateInput()
    )
    end_date = forms.DateField(
        label='结束日期',
        required=False,
        widget=DateInput()
    )

    def clean(self):
        cleaned_data = super().clean()
        start = cleaned_data.get('start_date')
        end = cleaned_data.get('end_date')
        # 验证至少填写一个日期
        if not start and not end:
            raise forms.ValidationError('请至少填写一个日期')
        # 若两个日期都填,确保开始日期不晚于结束日期
        if start and end and start > end:
            raise forms.ValidationError('开始日期不能晚于结束日期')
        return cleaned_data

二、传统Django表单提交方法

适合不需要无刷新交互的基础场景:

1. 视图函数处理

# views.py
from django.shortcuts import render
from .models import Offer
from .forms import DateRangeFilterForm

def filter_offers(request):
    offers = Offer.objects.all().order_by('expiration_date')
    form = DateRangeFilterForm(request.POST or None)

    if request.method == 'POST' and form.is_valid():
        start_date = form.cleaned_data['start_date']
        end_date = form.cleaned_data['end_date']
        # 根据日期筛选数据
        if start_date:
            offers = offers.filter(expiration_date__gte=start_date)
        if end_date:
            offers = offers.filter(expiration_date__lte=end_date)

    context = {
        'form': form,
        'filtered_offers': offers
    }
    return render(request, 'your_template.html', context)

2. 模板调整

<!-- your_template.html -->
<form method="POST">
    {% csrf_token %}
    {{ form|crispy }}
    <input type="submit" value="筛选">
</form>

<!-- 显示筛选结果 -->
{% if filtered_offers %}
<table>
    <thead>
        <tr>
            <th>过期日期</th>
            <!-- 其他需要展示的字段 -->
        </tr>
    </thead>
    <tbody>
        {% for offer in filtered_offers %}
        <tr>
            <td>{{ offer.expiration_date }}</td>
            <!-- 其他字段内容 -->
        </tr>
        {% endfor %}
    </tbody>
</table>
{% endif %}

三、HTMX现代无刷新方法

HTMX可实现页面无刷新提交表单并更新结果,符合现代交互体验:

1. 引入HTMX

在模板头部添加HTMX资源:

<script src="https://unpkg.com/htmx.org@1.9.10"></script>

2. 修改模板表单

给表单添加HTMX属性,指定提交地址、目标元素和更新方式:

<!-- your_template.html -->
<form hx-post="{% url 'filter_offers' %}" hx-target="#offer-results" hx-swap="innerHTML">
    {% csrf_token %}
    {{ form|crispy }}
    <input type="submit" value="筛选">
</form>

<!-- 用于显示筛选结果的容器 -->
<div id="offer-results">
    {% include 'offer_results.html' %}
</div>

3. 拆分结果模板(offer_results.html)

把结果表格单独做成片段模板,方便HTMX局部更新:

<!-- offer_results.html -->
{% if filtered_offers %}
<table>
    <thead>
        <tr>
            <th>过期日期</th>
            <!-- 其他字段 -->
        </tr>
    </thead>
    <tbody>
        {% for offer in filtered_offers %}
        <tr>
            <td>{{ offer.expiration_date }}</td>
            <!-- 其他字段内容 -->
        </tr>
        {% endfor %}
    </tbody>
</table>
{% else %}
<p>暂无符合条件的数据</p>
{% endif %}

4. 调整视图函数适配HTMX

判断是否为HTMX请求,仅返回结果片段而非完整页面:

# views.py
from django.shortcuts import render
from .models import Offer
from .forms import DateRangeFilterForm

def filter_offers(request):
    offers = Offer.objects.all().order_by('expiration_date')
    form = DateRangeFilterForm(request.POST or None)

    if request.method == 'POST' and form.is_valid():
        start_date = form.cleaned_data['start_date']
        end_date = form.cleaned_data['end_date']
        if start_date:
            offers = offers.filter(expiration_date__gte=start_date)
        if end_date:
            offers = offers.filter(expiration_date__lte=end_date)

    context = {'filtered_offers': offers}
    # 若为HTMX请求,仅返回结果片段
    if request.headers.get('HX-Request'):
        return render(request, 'offer_results.html', context)
    # 普通请求返回完整页面
    context['form'] = form
    return render(request, 'your_template.html', context)

关键注意点

  • 日期筛选使用Django ORM的__gte(大于等于)和__lte(小于等于)查询条件,精准匹配范围。
  • 表单验证确保至少填写一个日期,避免无效筛选操作。
  • HTMX通过HX-Request请求头识别无刷新请求,返回对应内容。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 11:40:23