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

如何为Django-filters下拉筛选框添加自动补全功能

问题

我用django-filters实现了筛选功能,当前是下拉菜单样式。想给这个下拉菜单加自动补全/搜索输入功能,尝试按帖子指引加了Select2Widget组件,但只在虚线前多了个空字段,没法输入内容,怀疑模板缺必要配置。附上代码:

filters.py

import django_filters
from django_select2.forms import Select2Widget
from .models import Consumo, Cliente

AÑO_CHOICES = (('2021', '2021'), ('2022', '2022'),)

class ConsumoFilter(django_filters.FilterSet):
    año = django_filters.ChoiceFilter(choices=AÑO_CHOICES, label='Año', widget=Select2Widget(attrs={'style':'width: 20ch', 'class':'form-select form-select-sm'}))
    name = django_filters.ModelChoiceFilter(queryset=Cliente.objects.all(), label='Clientes', widget=Select2Widget(attrs={'style':'width: 85ch','class': 'form-select form-select-sm'}))
    
class Meta:
    model = Consumo
    fields = ['name', 'año']

模板文件

{% extends 'clientes/base.html' %}
{% load static %}

{% block title %}Title{% endblock %}

{% block head %}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.13/js/select2.min.js" integrity="sha512-2ImtlRlf2VVmiGZsjm9bEyhjGW4dU7B6TNwh/hx/iSByxNENtj3WVE6o/9Lj4TJeVXPi4bnOIMXFIJJAeufa0A==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.13/css/select2.min.css" integrity="sha512-nMNlpuaDPrqlEls3IX/Q56H36qvBASwb3ipuo3MxeWbsQB1881ox0cRv7UPTgBlriqoynt35KjEwgGUeUXIPnw==" crossorigin="anonymous" referrerpolicy="no-referrer" />

{% endblock %}

{% block content %}

<div class="card" style="margin-top: 20px; margin-bottom: 20px;">
   <div class="card-body">
     <h4 class="card-title">Consumos</h4>
     <h6 class="card-subtitle mb-2 text-muted">Consumos por cliente</h6>
     <hr>
    
       <div class="container">
           <div class="row">
               <div class="col-lg-12">
                   <form method="get">
                       {{ consumo_filter.form }}
                    
                       <br>
                       <button type="submit" class="btn btn-sm btn-primary">Buscar</button>
                   </form>
                   <hr>

            </div>

        </div>
    </div>

  </div>
</div>

{% endblock %}

{% block javascript %}
{% endblock %}

解决方案

问题根源

你已经引入了Select2的CSS和JS,但没有初始化Select2组件,所以只是渲染了基础的Select2 DOM结构,但没激活它的搜索/自动补全功能。另外,Bootstrap的form-select类和Select2的样式冲突,会导致显示异常。

修复步骤

  1. 修改filters.py的widget属性:移除form-select form-select-sm类,避免样式冲突:
import django_filters
from django_select2.forms import Select2Widget
from .models import Consumo, Cliente

AÑO_CHOICES = (('2021', '2021'), ('2022', '2022'),)

class ConsumoFilter(django_filters.FilterSet):
    año = django_filters.ChoiceFilter(choices=AÑO_CHOICES, label='Año', widget=Select2Widget(attrs={'style':'width: 20ch;'}))
    name = django_filters.ModelChoiceFilter(queryset=Cliente.objects.all(), label='Clientes', widget=Select2Widget(attrs={'style':'width: 85ch;'}))
    
    class Meta:
        model = Consumo
        fields = ['name', 'año']
  1. 在模板的javascript块中初始化Select2:
    把模板里的{% block javascript %}部分替换为:
{% block javascript %}
<script>
$(document).ready(function() {
    // 批量初始化所有Select2组件
    $('.django-select2').select2({
        placeholder: "Selecciona una opción",
        allowClear: true // 可选:添加清空按钮
    });
});
</script>
{% endblock %}
  1. 可选:自定义单个字段的配置
    如果需要给不同字段设置不同的占位符或行为,可以单独初始化:
$(document).ready(function() {
    $('#id_name').select2({
        placeholder: "Busca un cliente...",
        allowClear: true
    });
    $('#id_año').select2({
        placeholder: "Selecciona un año",
        allowClear: true
    });
});

关键说明

  • django-select2的Select2Widget会自动给元素加上django-select2类,所以可以通过这个类批量初始化
  • 必须在DOM加载完成后初始化Select2,所以要用$(document).ready()包裹代码
  • 移除Bootstrap的form-select类是为了避免样式覆盖,保证Select2正常显示

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 12:05:37