As a Python developer, I’ve worked extensively with Django and its ORM. One challenge I often encountered is filtering querysets to exclude certain records, essentially a “not in” filter. While Django’s ORM is powerful, understanding the best ways to implement “not in” queries can save you time and improve your app’s performance.
In this article, I’ll walk you through how to effectively use the “not in” filter in Django. Whether you’re building an e-commerce platform filtering out out-of-stock products or a job board excluding certain job categories, these techniques will come in handy.
Let’s dive into some easy methods, complete with clear examples tailored for real-world scenarios.
What Does “Not In” Mean in Django ORM?
In SQL, the NOT IN clause excludes rows matching a list of values. Django ORM lets you do this cleanly using the exclude() method combined with __in lookup.
For example, if you want to get all employees who are not in a specific department, you can use:
Employee.objects.exclude(department__in=['HR', 'Finance'])This excludes employees belonging to HR or Finance departments.
Read How to Encrypt and Decrypt Passwords in Django
Method 1: Use exclude() with __in Lookup
This is the most common and straightforward way to filter out records matching a list of values.
Example: Exclude Certain States from a Queryset
Suppose you’re building a USA-based real estate app and want to show listings not located in California, Texas, or Florida.
from django.db import models
class Listing(models.Model):
address = models.CharField(max_length=255)
state = models.CharField(max_length=2) # State abbreviation, e.g., 'CA', 'TX'
# Query to exclude listings from CA, TX, and FL
excluded_states = ['CA', 'TX', 'FL']
listings = Listing.objects.exclude(state__in=excluded_states)
for listing in listings:
print(listing.address, listing.state)Here, exclude(state__in=excluded_states) filters out all listings from those states.
Why I Like This Method
- It’s simple and readable.
- Uses Django’s built-in ORM capabilities.
- Efficient SQL is generated under the hood.
I executed the above example code and added the screenshot below.

Method 2: Use Q Objects with Negation
For more complex queries, combining multiple conditions with Q objects and negation (~) can be powerful.
Example: Exclude Employees in Certain Departments or Job Titles
Imagine you have an employee directory and want to exclude those in HR or with the title “Intern”.
from django.db.models import Q
excluded_departments = ['HR']
excluded_titles = ['Intern']
employees = Employee.objects.filter(
~Q(department__in=excluded_departments) & ~Q(title__in=excluded_titles)
)
for emp in employees:
print(emp.name, emp.department, emp.title)Using ~Q() negates the condition, effectively filtering out employees in HR or interns.
When to Use This
- When combining multiple exclusion criteria.
- When you want to negate complex conditions.
- For dynamically building queries.
I executed the above example code and added the screenshot below.

Check out Python Django Form Validation
Method 3: Filter in Django Templates (Less Common)
Sometimes you want to filter data directly in templates. Django templates don’t support complex query filters, but you can pass filtered querysets from views or use custom template filters.
Example: Custom Template Filter to Exclude Items
Create a custom filter to exclude items from a list in a template.
# templatetags/custom_filters.py
from django import template
register = template.Library()
@register.filter
def exclude_items(queryset, excluded_list):
return queryset.exclude(id__in=excluded_list)In your template:
{% load custom_filters %}
{% with excluded_ids="1,2,3" %}
{% with excluded_ids_list=excluded_ids|split:"," %}
{% for item in items|exclude_items:excluded_ids_list %}
{{ item.name }}
{% endfor %}
{% endwith %}
{% endwith %}This is less efficient and generally not recommended for large datasets, but useful in some cases.
Real-World Use Case: Filter Job Listings Not in Certain Categories
Let’s say you’re building a job portal for the USA market. You want to display all jobs except those in “Retail” or “Hospitality” sectors.
excluded_categories = ['Retail', 'Hospitality']
jobs = JobListing.objects.exclude(category__in=excluded_categories)
for job in jobs:
print(job.title, job.category)This approach helps users focus on relevant job sectors.
Read the Login system in Python Django
Tips for Using “Not In” Filters Efficiently
- Always use
exclude()with__infor simple “not in” filters. - Use
Qobjects for complex negations and multiple conditions. - Avoid filtering large datasets in templates; do it in views.
- Index your database fields used in filters for performance.
- Test your queries with
.queryattribute to see the generated SQL.
Using the “not in” filter in Django is simple once you know the right approach. I’ve found that combining exclude() with __in lookup covers most cases efficiently, while Q objects provide the flexibility needed for complex scenarios.
Try these methods in your next Django project, and you’ll find filtering data by exclusion becomes second nature.
You may read:

I am Bijay Kumar, a Microsoft MVP in SharePoint. Apart from SharePoint, I started working on Python, Machine learning, and artificial intelligence for the last 5 years. During this time I got expertise in various Python libraries also like Tkinter, Pandas, NumPy, Turtle, Django, Matplotlib, Tensorflow, Scipy, Scikit-Learn, etc… for various clients in the United States, Canada, the United Kingdom, Australia, New Zealand, etc. Check out my profile.