Как использовать Substr с выражением F
Я пытаюсь создать набор Func
классов, построенных на fuzzystrmatch
расширении postgres.
Например, у меня есть эта обертка, которая принимает выражение Expression и поисковый запрос и возвращает расстояние Левенштейна:
class Levenshtein(Func):
"""This function calculates the Levenshtein distance between two strings:"""
template = "%(function)s(%(expressions)s, '%(search_term)s')"
function = "levenshtein"
def __init__(self, expression, search_term, **extras):
super(Levenshtein, self).__init__(
expression,
search_term=search_term,
**extras
)
Вызывается так, используя F Expression
:
Author.objects.annotate(lev_dist=Levenshtein(F('name'),'JRR Tolkien').filter(lev_dist__lte=2)
Однако если поле 'name'
здесь больше 255, то возникает ошибка:
И источник, и цель могут быть любой не нулевой строкой, максимум 255 символов.
Я могу усечь имя, когда аннотирую с помощью Substr
:
Author.objects.annotate(clipped_name=Substr(F('name'),1,250))
Но я не могу понять, как разместить эту логику внутри func, который я размещаю внутри ExpressionWrapper
и устанавливаю output_field
согласно документации :
class Levenshtein(Func):
"""This function calculates the Levenshtein distance between two strings:"""
template = "%(function)s(%(expressions)s, '%(search_term)s')"
function = "levenshtein"
def __init__(self, expression, search_term, **extras):
super(Levenshtein, self).__init__(
expression=ExpressionWrapper(Substr(expression, 1, 250), output_field=TextField()),
search_term=search_term,
**extras
)
Хотя в документации это не очень понятно, просто путем экспериментов выяснилось, что ответ заключается в удалении дополнительного определения expression
и передаче ExpressionWrapper
непосредственно в качестве первого аргумента:
class Levenshtein(Func):
"""This function calculates the Levenshtein distance between two strings:"""
template = "%(function)s(%(expressions)s, '%(search_term)s')"
function = "levenshtein"
def __init__(self, expression, search_term, **extras):
super(Levenshtein, self).__init__(
ExpressionWrapper(Substr(expression, 1, 250), output_field=TextField()),
search_term=search_term,
**extras
)