如何在django中使用postgres对Accent不敏感的过滤器?

时间:2011-04-11 10:16:04

标签: django postgresql

您好我发现在postgres数据库中,我们无法配置默认重音敏感度(在旧邮件交换机上)。

有没有办法让_icontains也对特殊字符(é,è,à,ç,ï)不敏感,或者我必须使用postgres regex用_iregex替换两边(ç-> c,é-> e ...)?

编辑: 这个问题很老,并且在1.8之前为django的用户保留。对于那些使用最新django版本的人来说,这里采用了新的方式:https://docs.djangoproject.com/en/dev/ref/contrib/postgres/lookups/#std:fieldlookup-unaccent

5 个答案:

答案 0 :(得分:8)

编辑:Django 1.8对postgresql内置的重音不敏感查找。 https://docs.djangoproject.com/en/dev/ref/contrib/postgres/lookups/#std:fieldlookup-unaccent

事实上,在postgres contrib(8.4+)中,有一个非常容易搜索的功能:

for postgres 9 / 8.5:

对于postgres 8.4:

这里是django的用法示例:

vals = MyObject.objects.raw(
        "SELECT * \
         FROM myapp_myobject \
         WHERE unaccent(name) LIKE \'%"+search_text+"%'")

您可以在比较之前对文本搜索应用应用unaccent。

我做的选择是:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# parts of credits comes to clarisys.fr
from django.db.backends.postgresql_psycopg2.base import *

class DatabaseOperations(DatabaseOperations):
    def lookup_cast(self, lookup_type):
        if lookup_type in('icontains', 'istartswith'):
            return "UPPER(unaccent(%s::text))"
        else:
            return super(DatabaseOperations, self).lookup_cast(lookup_type)

class DatabaseWrapper(DatabaseWrapper):
    def __init__(self, *args, **kwargs):
        super(DatabaseWrapper, self).__init__(*args, **kwargs)
        self.operators['icontains'] = 'LIKE UPPER(unaccent(%s))'
        self.operators['istartswith'] = 'LIKE UPPER(unaccent(%s))'
        self.ops = DatabaseOperations(self)

在文件夹中使用此文件base.py,并将此文件夹用作db后端。 icontains和istartswith现在是案例和重音不敏感。

答案 1 :(得分:7)

我设法从postgresql contrib安装unaccent,但是this answer that patches django没有用。 django.db.utils上的load_backend强制后端名称以django.db.backends开头。

对我有用的解决方案是将此代码插入我的一个模块中:

from django.db.backends.postgresql_psycopg2.base import DatabaseOperations, DatabaseWrapper

def lookup_cast(self, lookup_type, internal_type=None):
    if lookup_type in('icontains', 'istartswith'):
        return "UPPER(unaccent(%s::text))"
    else:
        return super(DatabaseOperations, self).lookup_cast(lookup_type, internal_type)

def patch_unaccent():
    DatabaseOperations.lookup_cast = lookup_cast
    DatabaseWrapper.operators['icontains'] = 'LIKE UPPER(unaccent(%s))'
    DatabaseWrapper.operators['istartswith'] = 'LIKE UPPER(unaccent(%s))'
    print 'Unaccent patch'

patch_unaccent()

现在,即使在django管理员内部,搜索工作也很好! 谢谢你的回答!

答案 2 :(得分:1)

我不相信你能够使用标准的Django字段查找,除非你将文本的非重音版本存储在另一列中并在那里进行查找。您可以使用editable = False添加重复列,并覆盖模型的save()方法以从原始重音文本更新该字段。

Python:Remove accents from unicode

PostgreSQL Wiki:Strip accents from strings, and output in lowercase

答案 3 :(得分:1)

我刚刚发布了(几天前)django-unaccent库,它将运算符添加到django ORM中以进行非紧密搜索。 它monkeypatch django ORM并使用postgres的unaccent()函数来执行此操作。

请检查出来=> https://github.com/djcoin/django-unaccent

答案 4 :(得分:0)

我正在为django和postgreSQL开发一个非同步的查找字段。它在github上:https://github.com/marianobianchi/django-accent-free-lookup

它现在工作正常,但仍需要大量工作。我正在使用它,它现在没有任何问题。

使用它的方法是为你想要进行不相关搜索的模型创建一个新的Manager(查看存储在项目managers.py文件末尾的示例)。

我已经实现的查找是:

  

“__ aexact”

     

“__ aiexact”

     

“__ acontains”

     

“__ aicontains”

它们等同于django附带的常见字段查找:

  

“__精确”

     

“__ iexact”

     

“__含”

     

“__ icontains”

区别在于它们对于最常见的重音字符是“重音不敏感”。