5

On my site user should have an ability to filter numbers, like *123*321*, that will match "666 123 555 321 111" or LIKE '%123%321%'.

By default django's orm escapes %-sign. I can use regex, or raw query, but is there some workaround?

UPD: i'll place it here for displaying another way.

integer_search = [] # for colorizing found substrings
if actual['integer']:
    integer_match = filter(None, actual['international'].split('*'))
    integer_search = integer_match
    integer_match = ''.join('%s[[:digit:]]*' % i for i in integer_match)
    integers = integers.filter(international__regex=integer_match)
night-crawler
  • 1,409
  • 1
  • 26
  • 39

1 Answers1

8

Yes, Django replaces all the % and _. From docs:

This means things should work intuitively, so the abstraction doesn't leak. For example, to retrieve all the entries that contain a percent sign, just use the percent sign as any other character

I would recommend you to use extra method. It is not really raw sql, although looks hacky:

YourModel.objects.extra(where=['title LIKE %s'], params=['%123%321%'])
San4ez
  • 8,091
  • 4
  • 41
  • 62
  • If you use this idea then check you are not creating an SQL injection attack. – Nick Craig-Wood May 30 '12 at 06:21
  • 1
    @NickCraig-Wood Yes, `params` prevents it. – San4ez May 30 '12 at 06:30
  • 1
    I just want to note, i think, if some tool disables original functionality, it should be a way to enable it with a method similar to that func's idea. I mean, that `__icontains=''` method already takes an argument, so why don't just to disable escaping in a place, like `.filter(field__icontains='%1', field__pescape=False)`? When i use extra() i go further. I just want to understand: django's developers skipped this because it's outside of django's philosophy, or this ability is not in a first-need list? Anyway, thanks, i'll mark your answer. – night-crawler May 30 '12 at 09:25
  • I don't like your suggestion, but you can [offer](https://code.djangoproject.com/) it to the community – San4ez May 31 '12 at 05:52