Поисковый запрос Django для сопоставления имен с акцентом и без него в PostgreSQL

Я использую Django с базой данных PostgreSQL. В моей базе данных есть таблица Users со столбцом name, в котором хранятся имена со специальными символами, такими как ударения и буква «Ñ». При выполнении поиска я хочу, чтобы результаты включали записи как с ударениями, так и без них. Например, если у меня есть пользователи с именами «lúlú» и «lulu», я хочу, чтобы в результатах поиска появились оба имени, независимо от того, содержит ли поисковый запрос ударения.

Вот мой текущий код для функции поиска:

def autocomplete(request):
result = []
try:
    if request.user.is_staff and request.user.is_active:
        columns = request.GET.get("column_name").split(",")
        value = request.GET.get("column_value")
        columns = [
            ("{}__icontains".format(column), request.GET.get("term"))
            for column in columns
        ]
        filters = request.GET.get("filters", [])
        if filters:
            filters = filters.split(",")
            filters = [tuple(x.split("=")) for x in filters]
        queryset = Filter(
            app_label=request.GET.get("app_label"),
            model_name=request.GET.get("model"),
        ).filter_by_list(columns, operator.or_, filters)
        for q in queryset:
            result.append(
                {"obj": q.to_json(), "label": str(q), "value": q.to_json()[value]}
            )
except AttributeError:
    pass
return HttpResponse(json.dumps(result, cls=Codec), content_type="application/json")

Как изменить поиск, чтобы игнорировать ударения и специальные символы, чтобы поиск по слову «lulu» также соответствовал слову «lúlú» и наоборот? Есть ли какие-либо рекомендации по работе с поиском без учета акцентов в Django с PostgreSQL?

Я полагаю, что вам придется написать вспомогательную функцию самостоятельно, вот скрипт, который подскажет вам направление:

words = [
    "Águeda",
    "Ålborg",
    "León",
    "Cancún",
    "Coimbra",
    "São Paulo",
    "Jönköping",
    "München",
    "Nykøbing Mors",
]

char_map = {
    "a": ["ã"],
    "A": ["Å", "Á"],
    "o": ["ó", "ö", "ø"],
    "u": ["ü", "ú"]
}


def find_chr(value):
    """
    Function to find a correspondent character
    in the map dict. Note that it returns original
    value if not found.
    """
    for key, chr_list in char_map.items():
        if value in chr_list:
            return key

    return value


def mutate(value):
    """
    Function that find if a word has a
    mutation. To increase performance
    the character verification is narrowed
    down to latin alphabet.
    """
    word = ""

    for chr in value:
        code_point = ord(chr)
        if (
            code_point >= ord("a")
            and code_point <= ord("z")
            or code_point >= ord("A")
            and code_point <= ord("Z")
        ):
            word += chr
        else:
            word += find_chr(chr)

    has_mutation = False if value == word else True

    return word, has_mutation


for w in words:
    search_array = [w]

    [mutation, has_mutation] = mutate(w)
    if has_mutation:
        search_array.append(mutation)

    print(search_array)

В результате получается search массив, который будет находиться в __in поиске.

Вернуться на верх