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

chr*_*e31 9 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

chr*_*e31 9

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

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

对于postgres 9/8.5:

对于postgres 8.4:

这里是django的用法示例:

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

您可以在比较之前对文本搜索应用应用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)
Run Code Online (Sandbox Code Playgroud)

使用此文件base.py的文件夹中,并使用该文件夹作为DB后端.icontains和istartswith现在是大小写和重音不敏感的.


bbr*_*rik 7

我设法从postgresql contrib安装unaccent,但补丁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()
Run Code Online (Sandbox Code Playgroud)

即使在django管理员内部,现在非正常搜索工作正常!谢谢你的回答!