2011-04-11 69 views
8

嗨我发现在postgres数据库上,我们不能配置默认的重音敏感性(在旧的邮件交换)。如何使用postgres在django中使用Accent-insensitive过滤器?

有没有办法让_icontains对特殊字符不敏感(é,è,à,ç,ï)或者我必须用postgres正则表达式来替换_iregex(ç-> c,é-> e ...)?

编辑: 这个问题是旧的,并保存为1.8之前django的用户。对于那些使用最新的Django版本,这里新的方式:https://docs.djangoproject.com/en/dev/ref/contrib/postgres/lookups/#std:fieldlookup-unaccent

回答

7

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

实际上在postgres的的contrib(8.4+)有一个unaccent函数容易地搜索:

为postgres的9/8.5:

for 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现在是大小写和变音不敏感的。

+0

如何将该文件夹用作数据库后端?我应该把它放在usr/local/lib/python2.7/dist-packages/django/db/backends目录下,或者我必须以某种方式声明它? – Falcoa 2015-02-19 14:36:41

+1

如果你不使用django 1.8,你可以简单地在你的数据库后端使用python虚线路径 DATABASES = {“default”:{ “ENGINE”:“my_app.my_backend_module”[...]}} – christophe31 2015-03-04 13:44:58

+0

i “已经添加在数据库后端的蟒蛇点缀路径,但有一个ImproperlyConfigured错误: 提高ImproperlyConfigured(ERROR_MSG) django.core.exceptions.ImproperlyConfigured:‘myAPP.backends.base’不是一个可用的后台数据库。 尝试使用 'django.db.backends.XXX',其中XXX为之一: u'mysql 'u'oracle',u'postgresql_psycopg2' ,u'sqlite3' 错误:没有模块指定基数 你知道该怎么做才能解决这个错误? – Falcoa 2015-03-07 22:46:26

1

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

的Python:Remove accents from unicode

PostgreSQL的维基:Strip accents from strings, and output in lowercase

+0

伤心的答案,我希望找到一个更好的方式做比在我的分贝每个可搜索文本字段中添加一列。我不确定我几乎可以肯定正则表达式可以完成这项工作。 – christophe31 2011-04-11 13:24:04

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): 
    if lookup_type in('icontains', 'istartswith'): 
     return "UPPER(unaccent(%s::text))" 
    else: 
     return super(DatabaseOperations, self).lookup_cast(lookup_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() 

现在unaccent搜索工作正常,甚至里面Django管理! 感谢您的回答!

+1

很奇怪,我的解决方案有一些特殊性。 该文件必须命名为base.py,settings.py必须使用其父文件夹作为后端,并且您不得在此文件中使用所用的类替换通配符。 (这是一种模块继承。) – christophe31 2011-09-15 13:19:59

+0

但是你的解决方案非常棒。我只是允许在settings.py级别设置行为。 (如果你把这个补丁放在一个单独的应用程序models.py中,你也可以这样做) – christophe31 2011-09-15 13:25:01

+1

这真的很奇怪,因为我没有命名文件base.py,并将它的父文件夹用作后端,但得到了错误配置错误。无论如何,谢谢你指出我在正确的方向。不受欢迎的搜索是我的客户真正需要的东西。 – bbrik 2011-09-16 18:05:08

0

我正在为django和postgreSQL寻找一个不起眼的查找字段。这是在GitHub上:https://github.com/marianobianchi/django-accent-free-lookup

它的正常工作,现在,但它仍然需要大量的工作。我正在使用它,它现在不显示任何问题。

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

我已经实现的查找是:

它们等同于公共领域查找随之而来的Django:

"__exact"

"__iexact"

"__contains"

"__icontains"

不同之处在于他们是“不区分重音”为最常见的重音字符。

+0

我发现我的方式更有趣,因为如果任何人使用管理员搜索,它将是无用的,甚至更多,如果你想切换到MySQL,你将失去重音不敏感,但其他东西会工作... – christophe31 2012-05-22 12:15:07

+0

你是对的,这只是另一个可能性,可能不是最适合每个人的。我没有用mysql测试它,但是如果mysql支持django regex lookup,这个应用程序应该和postgreSQL一样好。 – marianobianchi 2012-05-22 14:14:03

+0

regexlookup使用SQL正则表达式语言或Python正则表达式语言的SQLite所以,如果你使用的正则表达式语法是synonim的Postgres和MySQL它应该工作,但它可能无法与SQLite的工作。 – christophe31 2012-05-23 07:18:16

1

我刚刚发布(前几天)的Django的unaccent库,运营商加入到Django的ORM的unaccent搜索。 它monkeypatch django ORM并使用postgres的unaccent()功能来做到这一点。

请检查了这一点=>https://github.com/djcoin/django-unaccent