How to perform OR, AND and NOT in Django QuerySet Filtering
Last Updated :
20 Aug, 2024
We can use the Q objects in django.db.models to create an OR, AND, and NOT filter in a Django query. The Q objects are used to form complex filtering by joining several conditions through logic operators like OR, AND, and NOT. In this article, we will learn to perform AND, OR, and NOT filters while fetching data from databases using Django ORM.
Introduction to Q Objects
By default, query filters in Django use AND logic. If you need to apply OR logic or if you want to do more complex queries involving multiple logical operations like AND, OR, and NOT, Q objects do the trick. Basically, Q objects can be combined with &, |, and ~ operators.
OR Condition
Imagine you have a model Book with fields title, author, and published_date, and you need to select all book where the title contains "Django" or the author contains "GFG".
Python
from django.db.models import Q
from myapp.models import Book
# Get all books where the title contains "Django" OR
# the author name contains "GFG".
books = Book.objects.filter(Q(title__icontains="Django") | Q(author__icontains="GFG"))
print('Books: ' books)
for book in books:
print(book.title, book.author, sep=', ')
Output:
Book: <QuerySet [<Book: Django for Beginners>, <Book: Coding for All>]>
Django for Beginners, GeeksForGeeks
Coding for All, GFG Learning
AND Condition
If you need to use AND logic to combine conditions explicitly, you can do the following using Q objects as well:
Python
# Get all articles where title contains "Django" AND content contains "Python"
book = Book.objects.filter(Q(title__icontains="Django") & Q(content__icontains="GFG"))
print('Books: ', books)
for book in books:
print(book.title, book.author, sep=', ')
Output:
Books: <QuerySet [<Book: Django Tutorial>]>
Django Tutorial, GFG Learning Center
NOT Condition
You can use the ~ operator (NOT) to exclude certain results.
Python
# Get all books where title does NOT contain "Django"
books = Book.objects.filter(~Q(title__icontains="Django"))
print('Book: ', books)
Output:
Book: <QuerySet [<Book: A technical Writer >, <Book: Biography of GFG>, <Book: Debug ToolBar Guid>, <Book: Coding for All>]>
Combining Multiple Conditions
You can combine several Q objects to create very specific queries.
Example: Complex Query
Get all articles whose title contains the word "Django" OR whose content contains the word "Python", AND whose date of publication is later than 1st January, 2022.
Python
books = Book.objects.filter(
(Q(title__icontains="Django") | Q(author__icontains="GFG")) &
Q(published_date__gt="2024-08-20")
)
for book in books:
print(book.title, book.author, book.published_date, sep=', ')
Output:
Coding for All, GFG Learning, 2024-08-22
Examples to Implement Django QuerySet Filtering
The following are a few examples of the application of Q objects within Django for handling advanced querying cases:
Example 1: Filtering Users by Several Criteria
Suppose you have a User model with fields like first_name, last_name, email, and is_active. You want to retrieve all users whose first name is "John" or last name is "Doe".
Python
from django.db.models import Q
from django.contrib.auth.models import User
# Find users where first name is "John" OR last name is "Doe"
Get all users with first_name John or last_name Doe.
users = User.objects.filter(Q(first_name='John') | Q(last_name='Doe'))
Example 2: Complex AND and OR Conditions
Suppose that you have a Product model defined with name, category and price fields. You want to select all products either in the "Electronics" category or with a price below $50, and in stock.
Python
from django.db.models import Q
from myapp.models import Product
# Find products where (category is "Electronics" OR price < 50) AND in_stock is True
products = Product.objects.filter
(Q(category='Electronics') | Q(price__lt=50)) & Q(in_stock=True)
)
Example 3: Excluding Records with NOT
Let's say you want to get all the records from a BlogPost model, excluding those for which the title includes "Django".
Python
from django.db.models import Q
from myapp.models import BlogPost
# Get all blog posts except those whose title contains "Django"
posts = BlogPost.objects.filter(~Q(title__icontains='Django'))
Example 4: Complex Filtering on Date Fields
Suppose you have an Event model with fields name, start_date, and end_date. Find all the events that either start after the date or have no end date specified.
Python
from django.db.models import Q
from myapp.models import Event
# Find events where start_date is after '2024-01-01' OR end_date is null
events = Event.objects.filter(Q(start_date__gt='2024-01-01') | Q(end_date__isnull=True))
Conclusion
In Django, the OR filter in a query is accomplished by Q objects. They not only facilitate OR but generally provide a way to construct more complex queries than the default AND logic in the module. You can filter using Q objects with the | operator to find results that have either of the conditions. This will come in very handy in a situation where you would want to fetch records that would satisfy at least one of several conditions. It will enhance the flexibility and power in data fetching through Django's ORM.