Open In App

How to Query Case-insensitive Data in Django ORM

Last Updated : 29 Nov, 2024
Comments
Improve
Suggest changes
Like Article
Like
Report

To query case insensitive data, Django provides several lookup methods that we can use like iexact, icontains, istartswith, iendswith, etc. In this article we will be discussing how to filter and query data from the database without caring if its upper or lowercase using Django ORM.

Let's say we have the following model in our Django project.

models.py

Python
from django.db import models

class Person(models.Model):
    id = models.PositiveIntegerField(primary_key=True)
    first_name = models.CharField(max_length=50)
    last_name = models.CharField(max_length=50)
    email = models.EmailField(max_length=50)

We will be querying a small dataset which consists of the following rows and columns as shown below:

data
Data

For simplicity purpose, we will be using Django shell in order to execute queries to fetch data from the table. We can open the Django shell by typing the following command in our terminal:

python manage.py shell

Also, we have added the data to our table by creating objects of our model class in Django shell by using the code:

Python
from myapp.models import Person

Person.objects.create(first_name="Leo", last_name="Johnson", email="[email protected]")
Person.objects.create(first_name="Galileo", last_name="Vincenzo", email="[email protected]")
Person.objects.create(first_name="Chris", last_name="Evans", email="[email protected]")
Person.objects.create(first_name="Christopher", last_name="Ward", email="[email protected]")


Using iexact Lookup

iexact is used to find the exact match for a particular field which is used as an argument to the filter method and has the following syntax:

ModelName.objects.filter(field_name__iexact="value")

Let's try to find a person with first name as "Chris" from our table using iexact lookup. Here our ModelName is Person, field_name is first_name and value is "Chris"

Python
from demo.models import Person

Person.objects.filter(first_name__iexact="Chris")

Output:


iexact
iexact lookup

We can see that this method has returned a query set which contains a person object with id of 3. We can crosscheck that it is indeed Chris Evans who has an id of 3 and iexact lookup has matched the first_name properly. Just to be clear even if we have passed "chris" to iexact it will still return the correct row.

Using icontains Lookup

icontains is used to find whether the following field contains the following case-insensitive data. It can be used by the following syntax which is similar to the previous one.

Python
from demo.models import Person

Person.objects.filter(first_name__icontains="Leo")

Output:

icontains
icontains lookup

We can see that the icontains lookup has returned two rows which has id 1 and 2 respectively. By referring to our dataset, we can say that it has selected Leo Johnson and Galileo Vincenzo since both of them contain the letters "leo".

Using istartswith and iendswith Lookup

This lookup is a special version of icontains and it helps us to check whether the data of a particular field of a row starts with or ends with specific characters and filter them out.

Let's find the person whose last name starts with "W" using istartswith lookup.

Python
from demo.models import Person

Person.objects.filter(last_name__istartswith="W")
istarts
istartswith lookup

It has selected the row having id=4 whose last name is "Ward" and starts with "W".

Python
from demo.models import Person

Person.objects.filter(email__iendswith=".com")
iends
iendswith lookup

We are trying to find whose email ends with ".com" using iendswith lookup. As we can see, it has returned a query set which contains our entire dataset, since all the people have their email ending in ".com".

Using Q objects to filter objects

We can use Q objects in order to apply logical operations to select specific rows of data from the table. Each query can be called on different fields and is wrapped inside a Q object between which we can apply logical operations like & (And), | (Or) and find the correct row according to our requirements. Make sure to import Q first before performing any queries.

Python
from demo.models import Person
from django.db.models import Q

Person.objects.filter(Q(first_name__icontains="chris") & Q(last_name__icontains="ans"))

Output:

qobject
Q object operations

We are trying to find people whose first name contains "crhis" and last name contains "ans". There is only one person following this condition and they are returned in the query set.

Case-insensitive Ordering

We can use Lower() along with order_by() method for arranging our rows in ascending order without considering if the first character of the string data contains upper or lowercase. If we need to arrange it in descending order we can use desc() method to do the job. Be sure to import Lower before performing any queries.

Python
from demo.models import Person
from django.db.models.functions import Lower

Person.objects.order_by(Lower('first_name'))
Person.objects.order_by(Lower('first_name').desc())

Output:

asc
Ascending order
desc
Descending order

Ascending order follows the pattern [C, C, G, L] whereas Descending order follows the pattern [L, G, C, C]. Here we are performing case insensitive string sort operation by lowercasing all the data while arranging them in order. Note that the actual data stored in the table is not converted to lowercase.

Conclusion

In this article we have specified few of lookups such as iexact, icontains, etc using which returns a queryset with which we can process them further or delete them altogether according to our use case. We have also seen how to combine multiple lookups using Q objects and logical operators which makes it easier to find specific rows using complex conditions spread across multiple fields of the table. We have also shown how to arrange the rows in ascending as well as descending order using Lower().


Next Article
Article Tags :
Practice Tags :

Similar Reads