Django SearchField

Posted on December 1, 2008. Filed under: django | Tags: , , |

Há muito tempo “manter um blog” estava na minha “To Do List” e os colegas da lista de discussão django-brasil me deram o “empurrão” que eu precisava.

Depois de participar da thread na lista, decidi que o SearchField seria o assunto do meu primeiro post. Portanto, esse post é uma consequência da thread iniciada por Diego Martins e da super dica e ajuda de Luciano Ramalho. Agradeço aqui aos dois camaradas.

Por Que SearchField?

A idéia do SearchField é armazenar dados num formato útil para buscas, de forma a indexar valores de vários atributos num só atributo. Além disso, o valor indexado tem os caracteres não-ascii substituídos por seus correspondentes na tabela ascii através da função to_ascii, que é uma adaptação do removedor de acentos. Assim, podemos ter uma comparação de “strings” no banco de dados considerando os valores de várias colunas e sem considerar os acentos.

Como Usar

O SearchField tem um atributo obrigatório: field_names, que é uma lista com os nomes dos campos que se deseja indexar.

Declaração da classe de modelo

class Test(models.Model):
    text = models.TextField()
    another_text = models.TextField()
    search_text = SearchField(field_names=['text', 'another_text'])

Integrando com o Site de Administração do Django

Para utilizar o SearchField no Site de Administração basta forçar que o valor da busca seja convertido com a função to_ascii. Segue abaixo o código do arquivo “admin.py”:

from django.contrib import admin

def queryset_ascii(self, request):
    if 'q' in request.GET:
        request.GET._mutable = True
        request.GET['q'] = to_ascii(request.GET['q'])
    return admin.ModelAdmin.queryset(self, request)

class TestAdmin(admin.ModelAdmin):
    list_display = ['text', 'another_text', 'search_text']
    search_fields = ['search_text']
    queryset = queryset_ascii

admin.site.register(Test, TestAdmin)

Função to_ascii

from unicodedata import normalize

def to_ascii(txt, codif='utf-8'):
    if not isinstance(txt, basestring):
        txt = unicode(txt)
    if isinstance(txt, unicode):
        txt = txt.encode('utf-8')
    return normalize('NFKD', txt.decode(codif)).encode('ASCII','ignore')

SearchField

from django.db import models

class SearchField(models.TextField):
    def pre_save(self, model_instance, add):
        search_text = []
        for field_name in self.field_names:
            val = unicode(to_ascii(getattr(model_instance, field_name)))
            search_text.append(val)
        value = u' '.join(search_text)
        setattr(model_instance, self.name, value)
        return value
    def __init__(self, field_names, *args, **kwargs):
        self.field_names = field_names
        kwargs['editable'] = False
        super(self.__class__, self).__init__(*args, **kwargs)

Read Full Post | Make a Comment ( 2 so far )

Liked it here?
Why not try sites on the blogroll...