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

如何在django-filter中结合PostgreSQL unaccent实现无重音过滤?

解决方案:将PostgreSQL unaccent扩展与django-filter结合使用

前提条件

确保已完成以下操作:

  • 在PostgreSQL数据库中安装unaccent扩展(可通过执行CREATE EXTENSION IF NOT EXISTS unaccent;完成)
  • Django项目中已启用django.contrib.postgres应用(添加到INSTALLED_APPS配置项)

方案1:自定义支持Unaccent的字符过滤器

创建通用的UnaccentCharFilter替代默认CharFilter,自动处理重音忽略逻辑:

import django_filters
from django.db.models import Func, Value

class UnaccentCharFilter(django_filters.CharFilter):
    def filter(self, qs, value):
        if not value:
            return super().filter(qs, value)
        
        # 对数据库字段和搜索值同时应用unaccent函数
        qs = qs.annotate(
            unaccented_field=Func(self.field_name, function='unaccent')
        ).filter(
            unaccented_field__icontains=Func(Value(value), function='unaccent')
        )
        return qs

在你的FilterSet中替换使用该过滤器:

class BranchesFilter(django_filters.FilterSet):
    name = UnaccentCharFilter(
        label='Filial',
        label_suffix='',
        field_name='name',
        lookup_expr='icontains',
    )
    
    class Meta:
        model = Branches
        fields = '__all__'

方案2:全局替换FilterSet默认字符过滤器

如果希望所有字符类型字段自动启用重音忽略,无需逐个修改过滤器,可创建基类FilterSet:

import django_filters

class UnaccentFilterSet(django_filters.FilterSet):
    @classmethod
    def filter_for_field(cls, field, field_name, lookup_expr='exact'):
        filter_instance = super().filter_for_field(field, field_name, lookup_expr)
        # 自动将所有CharFilter替换为UnaccentCharFilter
        if isinstance(filter_instance, django_filters.CharFilter):
            return UnaccentCharFilter(
                field_name=field_name,
                lookup_expr=lookup_expr,
                label=filter_instance.label,
                label_suffix=filter_instance.label_suffix
            )
        return filter_instance

后续所有FilterSet继承该基类即可:

# 无需手动定义字段,自动生成带unaccent的过滤器
class BranchesFilter(UnaccentFilterSet):
    class Meta:
        model = Branches
        fields = '__all__'

# 需要自定义字段属性时,仍可手动定义
class BranchesFilter(UnaccentFilterSet):
    name = UnaccentCharFilter(
        label='Filial',
        label_suffix='',
        lookup_expr='icontains',
    )
    
    class Meta:
        model = Branches
        fields = '__all__'

效果验证

使用过滤器搜索时,输入带重音的字符(如México)会匹配到不带重音的记录(如Mexico),反之亦然,无需修改原有搜索逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 18:42:26