2011-04-11 38 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