【问题标题】:How to ignore special characters from the search field in Django如何忽略 Django 搜索字段中的特殊字符
【发布时间】:2023-02-15 21:41:17
【问题描述】:

该模型类似于

class Product(BaseModel):
    name = models.CharField(db_column='name', max_length=200, blank=False, null=False, unique=True)

视图是

class ProductViewSet(BaseViewSet):
    queryset = Product.objects.all()
    ...
    filterset_class = ProductFilter

过滤器是

class ProductFilter(django_filters.FilterSet):
    search = django_filters.CharFilter(field_name='name', lookup_expr='icontains')

    class Meta:
        model = Product
        fields = []

现在.. 如果名称字段的值类似于“This is a/sample”并且搜索文本是“asample”。我想退回那一行。

提前致谢。

【问题讨论】:

  • 您将无法通过对数据库进行简单的筛选查询来执行此操作——您需要使用 Elasticsearch 之类的工具来为您的搜索数据编制索引,然后对其运行查询。有许多可用于 Django 的 Elasticsearch 库。
  • 您使用哪个数据库?
  • @IainShelvington mysql

标签: django django-rest-framework django-filter


【解决方案1】:

如果问题仅针对一个特殊字符,即。 '/' 然后你可以像这样用 Replace 创建一个自定义过滤器方法:

class ProductFilter(django_filters.FilterSet):
    def filter_without_special_chars(self, queryset, field, value):
        return queryset.annotate(search_field=Replace('name', Value('/'), Value('')).filter(search_field__icontains=value)

    search = django_filters.CharFilter(method='filter_without_special_chars')

    class Meta:
        model = Product
        fields = []

你也可以这样做多个特殊字符但它不会是最佳解决方案,我建议您使用弹性搜索(或类似的东西)为了那个原因。

对于多个字符替换,函数看起来像这样:

def filter_without_special_chars(self, queryset, field, value):
        return queryset.annotate(sf1=Replace('name', Value('!'), Value('')),
                                 sf2=Replace('sf1', Value('%'), Value(''))).filter(sf2__icontains=value)

【讨论】:

  • 谢谢@Neeraj ... icontains 如何处理它。
  • @sadat 只需在您的参数中添加 __icontains 即可。我会更新回复
【解决方案2】:

使用目前支持 'unaccent' 扩展的 PostGreSQL。这使得仅键入“ano”时就可以搜索“año”。

最好的是,您可以决定是否为每个过滤器使用此扩展,例如使用

Person.objects.filter(first_name__unaccent__icontains=search)

将数据库切换到 PostgreSQL 并添加 unaccent 扩展名,如下所示:

@SaeX 在另一个线程中的部分回答: How can I activate the unaccent extension on an already existing model


需要手动制作和应用迁移文件。

  1. 首先,创建一个空迁移:

    ./manage.py makemigrations myapp --empty

    1. 然后打开文件并添加 UnaccentExtension 到操作:
    from django.contrib.postgres.operations import UnaccentExtension
    
    
    class Migration(migrations.Migration):
    
        dependencies = [
            (<snip>)
        ]
    
        operations = [
            UnaccentExtension()
        ]
    
    1. 现在使用./manage.py migrate.应用迁移

    如果您在最后一步遇到以下错误:

    django.db.utils.ProgrammingError: permission denied to create extension "unaccent"
    HINT:  Must be superuser to create this extension.
    

    ...然后通过执行 postgres# ALTER ROLE <user_name> SUPERUSER 暂时允许您的用户拥有超级用户权限;及其对应的 NOSUPERUSER。 pgAdminIII 也可以做到这一点。

    现在享受使用 Django 的 unaccent 功能:

    >>> Person.objects.filter(first_name__unaccent=u"Helène")
    [<Person: Michels Hélène>]
    

    同样,这个答案的一部分属于@SaeX


    重要的

    但对我来说他的回答仍然没有用,所以不要忘记 在 INSTALLED_APPS (settings.py) 中添加行 django.contrib.postgres

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多