Skip to content Skip to sidebar Skip to footer

Custom Lookup Is Not Being Registered In Django

I've created a custom lookup. I'm using it for a query, however, when I do so, the error Related Field got invalid lookup: lcb is thrown. I'm assuming that this is because this cus

Solution 1:

Edit 2

It looks like some of this confusion might be sorted out in later versions of django... Edit 1 below is for 1.10, but the code is different in tip so perhaps this has now been fixed. You could try upgrading to 1.11 and see if that fixes it. But the options I listed below are still worth a try if that doesn't work.

Edit 1

I realized that I misread the exception in my initial answer. Actually, the exception being hit is the one in django.db.models.fields.related.ForeignObject.get_lookup, and the code there is much clearer that django does not support custom lookups on Relational fields:

classForeignObject(RelatedField):

    ...

    def get_lookup(self, lookup_name):
        iflookup_name== 'in':
            return RelatedIn
        eliflookup_name== 'exact':
            return RelatedExact
        eliflookup_name== 'gt':
            return RelatedGreaterThan
        eliflookup_name== 'gte':
            return RelatedGreaterThanOrEqual
        eliflookup_name== 'lt':
            return RelatedLessThan
        eliflookup_name== 'lte':
            return RelatedLessThanOrEqual
        eliflookup_name== 'isnull':
            return RelatedIsNull
        else:
            raise TypeError('Related Field got invalid lookup: %s' % lookup_name)

    ...

There are a couple of things is one thing you could try to get it to work though:

  1. Implement a custom lookup on one of the fields through the many to many relationship, so you'd have a query like

    applications = applications.filter(
        pets__id__lcb=house.allowed_pets.values_list('id', flat=True))
    

    I was able to get something along these lines to work using the IN operator.

  2. Alternatively, you may be able to subclass the ForeignObject you are using and override get_lookup so that it doesn't throw an exception for your new operator... no doubt there would be a bit of a fiddle you'd have to do to get that to work though.Edit: I tried this, and it didn't work because it's more complicated than that, and for a join operation it's the implicit field from the right-hand table that is the Field used, so subclassing the Field for the left hand table was not enough. Option 1 definitely seems the right way to go about it.

Original answer

I believe the exception is telling you that django won't attempt to use custom lookups for relational fields. Given that you mention it I'm guessing that pets is a ManyToManyField, i.e. a relational field, and so I guess that your lookup has been registered, django is just refusing to use it.

The bit of code in django you are hitting (in django.db.models.sql.query.Query.build_filter()) is:

....
if field.is_relation:
    # No support for transforms for relational fields
    num_lookups = len(lookups)
    if num_lookups > 1:
        raise FieldError('Related Field got invalid lookup: {}'.format(lookups[0]))
....

I can't say I fully understand the rationale, but that certainly would explain why whatever mechanism you tried to use to register the lookup you got the same result.

It seems to be a not-very-well documented issue. The only thing online I could find out about it (with 10 minutes searching) was this, where someone else came to the same conclusion.

Post a Comment for "Custom Lookup Is Not Being Registered In Django"