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

如何在Django API视图中实现西语特殊字符与标准字符的过滤兼容

实现支持西班牙语重音字符兼容过滤的Django API

要让你的API过滤器支持用无重音字符匹配带重音的字段值(比如用cancion匹配canción),可以通过以下两种方案实现:

方案一:利用数据库函数动态去重音(推荐,无额外存储)

1. 数据库准备(以PostgreSQL为例)

首先确保PostgreSQL安装了unaccent扩展,可通过迁移文件添加:

# 在你的app下创建迁移文件(比如0002_add_unaccent_extension.py)
from django.db import migrations, models

class Migration(migrations.Migration):
    dependencies = [
        ('your_app_name', '0001_initial'),  # 替换为你的app最新迁移文件
    ]

    operations = [
        migrations.RunSQL('CREATE EXTENSION IF NOT EXISTS unaccent;'),
    ]

执行迁移:python manage.py migrate

2. 自定义FilterSet

创建支持去重音过滤的FilterSet,重写字段过滤逻辑:

from django_filters import rest_framework as filters
from django.db.models import Func, Value
from .models import Weeks

# 定义调用数据库unaccent函数的Func类
class Unaccent(Func):
    function = 'UNACCENT'
    template = "%(function)s(%(expressions)s)"

class OpenWeeksFilterSet(filters.FilterSet):
    activity = filters.CharFilter(method='filter_unaccented_field')
    discipline = filters.CharFilter(method='filter_unaccented_field')

    def filter_unaccented_field(self, queryset, name, value):
        # 对数据库字段和用户输入同时去重音,再做包含匹配
        return queryset.annotate(
            unaccented_field=Unaccent(name)
        ).filter(unaccented_field__icontains=Unaccent(Value(value)))

    class Meta:
        model = Weeks
        fields = ['activity', 'discipline']

3. 更新API视图

将原视图的filterset_fields替换为自定义的filterset_class:

class OpenWeeksAPIView(generics.ListCreateAPIView):
    queryset = Weeks.objects.all()
    serializer_class = OpenWeeksSerializer
    filter_backends = [DjangoFilterBackend]
    filterset_class = OpenWeeksFilterSet  # 替换原filterset_fields
    pagination_class = DefaultPagination

MySQL适配

如果使用MySQL,将Unaccent类替换为以下实现(依赖utf8mb4字符集):

class Unaccent(Func):
    function = 'CONVERT'
    template = "%(function)s(%(expressions)s USING utf8mb4) COLLATE utf8mb4_general_ci"

同时确保你的数据库表字符集为utf8mb4,排序规则为utf8mb4_general_ci(该规则会自动忽略重音差异)。

方案二:预生成无重音字段(跨数据库通用)

通过在模型中添加无重音字段,保存数据时自动生成,过滤时直接匹配该字段:

1. 修改模型

安装unidecode库:pip install unidecode,然后更新模型:

from django.db import models
from unidecode import unidecode

class Weeks(models.Model):
    activity = models.CharField(max_length=255)
    discipline = models.CharField(max_length=255)
    # 添加不可编辑的无重音字段
    activity_unaccented = models.CharField(max_length=255, editable=False)
    discipline_unaccented = models.CharField(max_length=255, editable=False)

    def save(self, *args, **kwargs):
        # 保存时自动生成无重音版本
        self.activity_unaccented = unidecode(self.activity)
        self.discipline_unaccented = unidecode(self.discipline)
        super().save(*args, **kwargs)

执行迁移:python manage.py makemigrations && python manage.py migrate

2. 配置FilterSet

class OpenWeeksFilterSet(filters.FilterSet):
    activity = filters.CharFilter(field_name='activity_unaccented', lookup_expr='icontains')
    discipline = filters.CharFilter(field_name='discipline_unaccented', lookup_expr='icontains')

    class Meta:
        model = Weeks
        fields = ['activity', 'discipline']

最后同样更新API视图的filterset_class即可。

内容的提问来源于stack exchange,提问作者Carlos S. C.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 16:05:27