How to Write Custom Lookups in Django?
Starting the Project Folder
To start the project use this command
django-admin startproject custom_lookup_project
cd custom_lookup_project
To start the app use this command
python manage.py startapp custom_lookup_app
Now add this app to the ‘settings.py’
INSTALLED_APPS = [
"django.contrib.admin",
"django.contrib.auth",
"django.contrib.contenttypes",
"django.contrib.sessions",
"django.contrib.messages",
"django.contrib.staticfiles",
"custom_lookup_app",
]
File Structure
Setting Necessary Files
custom_lookup_app/models.py : Below code defines a Django model called Person
with a single field name
of type CharField with a maximum length of 100 characters.
# custom_lookup_app/models.py
from django.db import models
class Person(models.Model):
name = models.CharField(max_length=100)
custom_lookup_app/views.py: Django view function searches for Person
objects based on a case-insensitive exact match to a query string provided in the request GET parameters. If a match is found, it renders the ‘index.html’ template with the matching persons
; otherwise, it renders an empty queryset
# custom_lookup_app/views.py
from django.shortcuts import render
from .models import Person
def search_person(request):
if 'query' in request.GET:
query = request.GET['query']
persons = Person.objects.filter(name__iexact=query)
else:
persons = Person.objects.none()
return render(request, 'index.html', {'persons': persons})
custom_lookup_project/lookups.py : Below,code defines a custom lookup CaseInsensitiveExact
for Django models, enabling case-insensitive exact matching in queries. It overrides the as_sql
method to generate SQL that converts both sides of the comparison to lowercase, facilitating a case-insensitive comparison. This lookup can be used for fields where case sensitivity is not desired, such as names or titles.
# custom_lookup_app/lookups.py
from django.db.models import Lookup
from django.db.models.functions import Lower
class CaseInsensitiveExact(Lookup):
lookup_name = 'iexact'
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 f"LOWER({lhs}) = LOWER({rhs})", params
custom_lookup_project/__init__.py : Below code enhances Django’s CharField to incorporate a custom lookup named CaseInsensitiveExact
, which facilitates case-insensitive exact matching in database queries within the custom_lookup_app
.
# custom_lookup_app/__init__.py
from django.db.models import CharField
from .lookups import CaseInsensitiveExact
CharField.register_lookup(CaseInsensitiveExact)
custom_lookup_project/urls.py : This is the URL which is connect views with templates.
from django.contrib import admin
from django.urls import path
from custom_lookup_app.views import search_person
urlpatterns = [
path('admin/', admin.site.urls),
path('', search_person, name='search_person'),
]
Creating GUI
templates/index.html : This HTML template displays search results for persons. It includes a search form where users can input a name to search. If there are matching persons, their names are listed; otherwise, it shows a message indicating no results were found.
<!-- templates/index.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Search Results</title>
</head>
<body>
<h1>Search Results</h1>
<form method="GET">
<input type="text" name="query" placeholder="Search by name" value="{{ request.GET.query }}">
<button type="submit">Search</button>
</form>
{% if persons %}
<ul>
{% for person in persons %}
<li>{{ person.name }}</li>
{% endfor %}
</ul>
{% else %}
<p>No results found.</p>
{% endif %}
</body>
</html>
admin.py: Here we are registering our models.
from django.contrib import admin
from .models import *
from django.db.models import Sum
admin.site.register(Person)
Deployment of the Project
Run these commands to apply the migrations:
python3 manage.py makemigrations
python3 manage.py migrate
Run the server with the help of following command:
python3 manage.py runserver
Output:
Video Demonstration
How to Write Custom Lookups in Django?
Custom lookups allow you to define custom filters that can be used in database queries. By default, Django provides a set of built-in lookups such as exact, icontains, gt, lt, etc., which allow you to perform common filtering operations on query sets. However, sometimes you may need to perform more complex or specialized filtering that isn’t covered by the built-in lookups. In this article, we will see how to write custom lookups in Django.