Поисковый запрос 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
поиске.