Согласование всего слова только в запросе Django

Я пытаюсь написать Django-запрос, который будет соответствовать целым словам. Основываясь на ответе здесь, я пробовал что-то вроде:

result = Model.objects.filter(text__iregex='\bsomeWord\b')

Но это не возвращает ожидаемый результат. Я также пробовал

result = Model.objects.filter(text__iregex=r'\bsomeWord\b')

безрезультатно. Моя конечная цель состоит в том, чтобы иметь возможность передавать строковую переменную, например:

result = Model.objects.filter(text__iregex=r'\b'+stringVariable+r'\b')

или

result = Model.objects.filter(text__iregex=r'\b %s \b'%stringVariable)

Но сейчас я даже не могу заставить его работать с необработанной строкой. Я использую PostgreSQL.

Ответ 1

Используйте '\ y' вместо '\ b', когда вы используете PostgreSQL, это потому, что Django передает ваше регулярное выражение прямо в PostgreSQL - поэтому ваш RegEx должен быть совместимым с этим. Вы должны быть в состоянии выполнить их из psql без каких-либо проблем.

result = Model.objects.filter(text__iregex=r"\y{0}\y".format(stringVariable))

См https://www.postgresql.org/docs/9.1/functions-matching.html#POSIX-CONSTRAINT-ESCAPES-TABLE

Ответ 2

Возможно, вы сможете получить что-то, отбросив регулярное выражение и используя несколько поисков django

result = Model.objects.filter(Q(text__contains=' someword ') |
                              Q(text__contains=' someword.') |
                              Q(text__istartswith = 'someword.' |
                              Q(text__istartswith = 'someword.' |
                              Q(text__iendswith = 'someword')

см. здесь для документов.

Я понимаю, что не очень элегантный (но упрощает обслуживание, если вы не поклонник регулярного выражения).

Ответ 3

У меня была та же проблема, которая пыталась совместить границы слов, используя совместимую с Perl escape-последовательность\b. Моя база данных - это MySQL.

Я решил проблему с помощью выражения класса символа [[: space:]], например.

        q_sum = Q()
        search_list = self.form.cleaned_data['search_all'].split(' ');
        for search_item in search_list:
            search_regex = r"[[:space:]]%s[[:space:]]" % search_item
            q_sum |= Q(message__iregex=search_regex)
        queryset = BlogMessages.objects.filter(q_sum).distinct()