Custom Lookups in Django

Nishanth G
Apr 14 · 3 min read

before we check on Custom Lookups, let’s see the basics and understand what is a Lookup

So what’s a Lookup …

As per the Django docs

Field lookups are how you specify the meat of an SQL WHERE clause. They’re specified as keyword arguments to the QuerySet methods filter(), exclude() and get().

not very clear but an example would make it so much more easy

Entry.objects.filter(id__in=[1, 3, 4])

in the above example ‘in’ is what is called a Lookup and what the above query does is filters all the Entry data where their id’s belong to any of the values in the list [1, 3, 4]

Now i hope you have some idea of how and where a Lookup is used

Django has many builtin lookups and if none are specified as such then the default is ‘exact’ for ex:

Entry.objects.get(id=14)

is the same as

Entry.objects.get(id__exact=14)

a few examples of builtin lookups are [in,iexact, contains , gt ,gte ,lt ,startswith ….]

you can check the link for rest of them: https://docs.djangoproject.com/en/3.1/ref/models/querysets/#field-lookups

Let’s jump and address the 🐘 in the 🏠 — — — — Custom 👀👆🏻

haha sry i got carried away with the emoji’s ,

So what and why do we need Custom Lookups ?

Why , the answer is simple bcz there might be no Lookup that would fetch you data as per your complex requirement

Lets check a very simple example from Djangodocs that would give u enough info to start with working on Custom Lookups

We will write a custom lookup ne which works opposite to exact. Author.objects.filter(name__ne='Jack') will translate to the SQL:

"author"."name" <> 'Jack'

This SQL is backend independent, so we don’t need to worry about different databases.

There are two steps to making this work. Firstly we need to implement the lookup, then we need to tell Django about it:

from django.db.models import Lookupclass NotEqual(Lookup):
lookup_name = 'ne'
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 <> %s' % (lhs, rhs), params

To register the NotEqual lookup we will need to call register_lookup on the field class we want the lookup to be available for. In this case, the lookup makes sense on all Field subclasses, so we register it with Field directly:

from django.db.models import Field
Field.register_lookup(NotEqual)

Lookup registration can also be done using a decorator pattern:

from django.db.models import Field@Field.register_lookup
class NotEqualLookup(Lookup):

for more info checkout: https://docs.djangoproject.com/en/3.1/howto/custom-lookups/

That’s all folks and as always if you have read so far then …..

Nerd For Tech

From Confusion to Clarification

Nerd For Tech

NFT is an Educational Media House. Our mission is to bring the invaluable knowledge and experiences of experts from all over the world to the novice. To know more about us, visit https://www.nerdfortech.org/.

Nishanth G

Written by

Avg Software Engineer , can’t write any post that takes more than 5 mins

Nerd For Tech

NFT is an Educational Media House. Our mission is to bring the invaluable knowledge and experiences of experts from all over the world to the novice. To know more about us, visit https://www.nerdfortech.org/.