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

Django项目中下拉菜单点击事件重复触发导致选中选项丢失的问题解决咨询

解决Dropdown点击选项时重复触发AJAX的问题

看起来你踩了原生click事件的坑——当你点击<select>元素展开下拉时触发AJAX没问题,但选择选项时,浏览器会再次触发<select>的click事件,导致你的AJAX重新执行,覆盖掉刚选中的选项。下面给你两种针对性的解决方案,适配不同的场景:


方案1:使用Bootstrap Select专属事件(推荐,适配Crispy Forms)

因为你用了Crispy Forms + Bootstrap,默认应该集成了Bootstrap Select插件。这个插件提供了show.bs.select事件,仅在下拉菜单展开时触发,选择选项时完全不会触发它,完美解决你的问题。

修改你的脚本部分:

$("#id_person").on('show.bs.select', function () {
    const reportValue = $("#id_report").val();
    const loadUrl = $("#PostForm").attr("data-person-url");
    
    $.ajax({
        url: loadUrl,
        data: { 'value': reportValue },
        success: function (optionsHtml) {
            $("#id_person").html(optionsHtml).selectpicker('refresh');
            console.log('加载的人员选项:', optionsHtml);
        }
    });
});

关键说明:

  • show.bs.select:Bootstrap Select的核心事件,只在下拉菜单开始展开时触发一次
  • selectpicker('refresh'):加载新选项后必须调用这个方法,让Bootstrap Select更新UI,否则新选项不会正常显示

方案2:原生Select的兼容方案

如果你的项目没有用Bootstrap Select,只用原生<select>,可以通过mousedown事件配合标志位来避免重复触发:

let isDropdownOpen = false;

$("#id_person")
  // 监听鼠标按下事件(比click更早触发,避免选项点击的冒泡)
  .on('mousedown', function () {
      if (!isDropdownOpen) {
          const reportValue = $("#id_report").val();
          const loadUrl = $("#PostForm").attr("data-person-url");
          
          $.ajax({
              url: loadUrl,
              data: { 'value': reportValue },
              success: function (optionsHtml) {
                  $("#id_person").html(optionsHtml);
                  console.log('加载的人员选项:', optionsHtml);
              }
          });
      }
      isDropdownOpen = !isDropdownOpen;
  })
  // 下拉关闭后重置标志位
  .on('blur', function () {
      isDropdownOpen = false;
  });

关键说明:

  • 用mousedown代替click:因为click会在选项选择后再次触发,而mousedown只会在第一次点击展开下拉时触发
  • 标志位isDropdownOpen:确保只有下拉未展开时才执行AJAX,避免重复调用

后端视图注意事项

确保你的ajax_load_persons视图返回的是正确的<option>标签格式,比如:

# views.py
from django.http import HttpResponse
from .models import Person

def ajax_load_persons(request):
    report_id = request.GET.get('value')
    # 根据你的模型关联逻辑调整过滤条件
    persons = Person.objects.filter(report__id=report_id)
    # 生成<option>标签字符串
    options = '\n'.join([f'<option value="{person.id}">{person.name}</option>' for person in persons])
    return HttpResponse(options)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.01 03:02:29