Skip to content

Instantly share code, notes, and snippets.

@Ryanb58
Created September 28, 2018 15:45
Show Gist options
  • Save Ryanb58/88ec965705166d4f2bc53fad5b4df015 to your computer and use it in GitHub Desktop.
Save Ryanb58/88ec965705166d4f2bc53fad5b4df015 to your computer and use it in GitHub Desktop.
Python monkey patch example.

Having an issue deep within django and realize we wanted a debugger. So we monkey patched the methods.


def fake_prep_for_like_query(self, x):
    """Prepares a value for use in a LIKE query."""
    from django.utils.encoding import force_text
    return force_text(x).replace("\\", "\\\\").replace("%", "\%").replace("_", "\_")

def fake_get_db_prep_lookup(self, lookup_type, value, connection,
                   prepared=False):
    """
    Returns field's value prepared for database lookup.
    """
    if not prepared:
        value = self.get_prep_lookup(lookup_type, value)
    if hasattr(value, 'get_compiler'):
        value = value.get_compiler(connection=connection)
    if hasattr(value, 'as_sql') or hasattr(value, '_as_sql'):
        # If the value has a relabel_aliases method, it will need to
        # be invoked before the final SQL is evaluated
        if hasattr(value, 'relabel_aliases'):
            return value
        if hasattr(value, 'as_sql'):
            sql, params = value.as_sql()
        else:
            sql, params = value._as_sql(connection=connection)
        return QueryWrapper(('(%s)' % sql), params)

    if lookup_type in ('regex', 'iregex', 'month', 'day', 'week_day',
                    'search'):
        return [value]
    elif lookup_type in ('exact', 'gt', 'gte', 'lt', 'lte'):
        return [self.get_db_prep_value(value, connection=connection,
                                    prepared=prepared)]
    elif lookup_type in ('range', 'in'):
        return [self.get_db_prep_value(v, connection=connection,
                                    prepared=prepared) for v in value]
    elif lookup_type in ('contains', 'icontains'):
        return ["%%%s%%" % connection.ops.prep_for_like_query(value)]
    elif lookup_type == 'iexact':
        return [connection.ops.prep_for_iexact_query(value)]
    elif lookup_type in ('startswith', 'istartswith'):
        from ipdb import set_trace;set_trace()
        return ["%s%%" % connection.ops.prep_for_like_query(value)]
    elif lookup_type in ('endswith', 'iendswith'):
        return ["%%%s" % connection.ops.prep_for_like_query(value)]
    elif lookup_type == 'isnull':
        return []
    elif lookup_type == 'year':
        if self.get_internal_type() == 'DateField':
            return connection.ops.year_lookup_bounds_for_date_field(value)
        else:
            return connection.ops.year_lookup_bounds(value)

from django.db import backends
backends.BaseDatabaseOperations.prep_for_like_query = fake_prep_for_like_query
from django.db.models import fields
fields.Field.get_db_prep_lookup = fake_get_db_prep_lookup
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment