Skip to content
Advertisement

Django NotEqual custom lookup on related field

I registered a custom lookup base on this answer and official documentation.

# core/custom_lookup.py

from django.db.models import Lookup


class NotEqual(Lookup):
    """Missing != operator."""
    lookup_name = 'ne'

    def as_sql(self, *args):
        lhs, lhs_params = self.process_lhs(*args)
        rhs, rhs_params = self.process_rhs(*args)
        return '{} <> {}'.format(lhs, rhs), lhs_params + rhs_params

I registered the custom lookup in my app config.

# core/apps.py

from django.apps import AppConfig
from django.db.models import Field
from .custom_lookup import NotEqual


class CoreConfig(AppConfig):
    default_auto_field = 'django.db.models.BigAutoField'
    name = 'core'

    def ready(self):
        Field.register_lookup(NotEqual)

Then i use it in the exclude method this way.

Customer.objects.all().filter(filter).exclude(private=True, user__ne=info.context.user).order_by('-created')

The idea here is to get all the customers where user is info.context.user (with private is False or True) OR user is NOT info.context.user but private is False but exclude customers where user is NOT info.context.user AND private is True

But whenever I play the query the error below is thrown

Related Field got invalid lookup: ne

Am I missing something on the registration of the lookup?

Advertisement

Answer

I bit explored and found the way. You should add Related field lookup because user is ForeignKey or OneToOneField I guess, So the code is,

core/custom_lookup.py

from django.db.models import Lookup
from django.db.models.fields.related_lookups import RelatedLookupMixin

class NotEqual(Lookup):
    """Missing != operator."""
    lookup_name = 'ne'

    def as_sql(self, *args):
        lhs, lhs_params = self.process_lhs(*args)
        rhs, rhs_params = self.process_rhs(*args)
        return '{} <> {}'.format(lhs, rhs), lhs_params + rhs_params

class NotEqualRelated(RelatedLookupMixin, Lookup):
    """Missing != operator."""
    lookup_name = 'nere'

    def as_sql(self, *args):
        lhs, lhs_params = self.process_lhs(*args)
        rhs, rhs_params = self.process_rhs(*args)
        return '{} <> {}'.format(lhs, rhs), lhs_params + rhs_params

core/apps.py

from django.apps import AppConfig
from django.db.models import Field
from .custom_lookup import NotEqual, NotEqualRelated
from django.db.models.fields.related import RelatedField, OneToOneField

class MainConfig(AppConfig):
    default_auto_field = 'django.db.models.BigAutoField'
    name = 'main'

    def ready(self):
        Field.register_lookup(NotEqual)
        OneToOneField.register_lookup(NotEqualRelated)

In your case you may need to add ForeignKey.register_lookup . please take a try this code and let me know if you face any issues.

2nd solution:

We can use a field lookup argument “__” so that we can compare the id of the foreign object (user) to another id (user from context in this case).

Customer.objects.all().filter(filter).exclude(private=True, user__id__ne=info.context.user.id).order_by('-created')
4 People found this is helpful
Advertisement