Open In App

How to Write Custom Lookups in Django?

Last Updated : 17 Apr, 2024
Improve
Improve
Like Article
Like
Save
Share
Report

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.

How to Write Custom Lookups in Django?

Below, are the Implementation of how to write custom lookups in Django in Python:

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

llo

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.

Python3
# 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

Python3
# 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.

Python3
# 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.

Python3
# 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.

Python3
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.

HTML
<!-- 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.

Python3
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:

kkk

Video Demonstration



Like Article
Suggest improvement
Previous
Next
Share your thoughts in the comments

Similar Reads