Opened 5 years ago

Closed 5 years ago

#30074 closed New feature (invalid)

Cannot Un-escape LIKE wildcards without .extra()

Reported by: Doug Dresser Owned by: nobody
Component: Database layer (models, ORM) Version: 2.1
Severity: Normal Keywords: QuerySet.extra
Cc: Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

Currently, django escapes wildcards used in SQL LIKE clauses. See here https://docs.djangoproject.com/en/dev/topics/db/queries/#escaping-percent-signs-and-underscores-in-like-statements.

At times, I have found it desirable to actually want wildcards, and there are only two options to replicate this to my knowledge:

1) Raw SQL using .extra()
2) Using a regular expression such as .filter(somefield__regex=<regex_lookup>)

The first option is undesirable because its using raw sql, not high level python. The second is undesirable because SQL REGEX is much much slower than using a LIKE clause with wildcards.

I propose adding an optional parameter (thus allowing backwards compatibility) within .filter(), such as .filter(somefield__contains=FO%BAR, escape=False) which will allow the filter expression to not escape the underscores and percentage signs.

Change History (1)

comment:1 by Simon Charette, 5 years ago

Resolution: invalid
Status: newclosed

Hello there,

Unfortunately the API you are suggesting through filter(escape=True) is backward incompatible. I'm also not convinced this use case is common enough to warrant the inclusion of such option given this can easily be implemented by registering a custom lookup.

e.g.

from django.db import models

class Like(models.Lookup):
    lookup_name = 'like'

    def as_sql(self, compiler, connection):
        lhs, lhs_params = self.process_lhs(compiler, connection)
        rhs, rhs_params = self.process_rhs(compiler, connection)
        params = lhs_params + rhs_params
        return '%s LIKE %s' % (lhs, rhs), params

models.CharField.register_lookup(Like)
models.TextField.register_lookup(Like)

Foo.objects.filter(bar__like='unescaped % or _')
Note: See TracTickets for help on using tickets.
Back to Top