[Fixed]-Django 1.4: Custom field and lookup override

1👍

Not entirely sure if there’s a proper JsonListField available for Django 1.4, I would think there might be one but not a 100% certain. Regardless, writing your own is at least more fun 🙂

A quick Google gave me these 2 results at least:


Looking at the get_db_prep_lookup() method it seems that you can’t easily do it with that:
https://github.com/django/django/blob/master/django%2Fdb%2Fmodels%2Ffields%2F__init__.py#L737-L771

def 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)
        prepared = True
    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 relabeled_clone method it means the
        # value will be handled later on.
        if hasattr(value, 'relabeled_clone'):
            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 ('search', 'regex', 'iregex', 'contains',
                       'icontains', 'iexact', 'startswith', 'endswith',
                       'istartswith', 'iendswith'):
        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 == 'isnull':
        return []
    else:
        return [value]

While changing the as_sql for the value might work, looking at the code slightly further tells me that it probably won’t.

Your best guess (it’s something I’ve done in the past and which worked just fine for me since 0.95) is to overwrite the Manager and let it return a custom QuerySet which modifies the _filter_or_exclude() method and rewrites the queries before they’re being sent.

👤Wolph

Leave a comment