Back to Blog
Python

Python Django ORM: filter, get, exclude, create, update, and delete

python django filter get exclude create update and delete: Learn how to use Django's ORM methods filter, get, exclude, create, update, and delete to query and modify d...

DjangoORMQuerySetCRUDPython
Django ORM operations diagram showing filter, get, exclude, create, update, and delete on a database table.

python django filter get exclude create update and delete requires a clear understanding of the core syntax, runtime behavior, and practical implementation patterns demonstrated in the examples below.

Django's ORM provides a set of methods that cover the most common database operations: filter, get, exclude, create, update, and delete. These methods are the backbone of data manipulation in Python Django applications, and understanding their behavior is essential for writing efficient and correct code. In this article, we explore each operation, its syntax, return types, and practical considerations.

Querying with filter and get

The filter() method returns a QuerySet containing objects that match the given lookup parameters. It is lazy, meaning the database query is not executed until the QuerySet is evaluated, such as when iterating over it or calling list() on it.

from myapp.models import Product # Returns all products with price > 100 expensive_products = Product.objects.filter(price__gt=100)

get() returns a single object that matches the lookup. It raises DoesNotExist if no object matches, and MultipleObjectsReturned if more than one object matches. Use get() when you expect exactly one result and want to handle the absence explicitly.

try: product = Product.objects.get(id=42) except Product.DoesNotExist: product = None

get() is not lazy; it executes the query immediately. If you only need to check existence, filter().exists() is more efficient.

Excluding Records with exclude

The exclude() method returns a QuerySet containing objects that do not match the given lookup parameters. It is the logical opposite of filter() and can be chained with other queryset methods.

# Returns all products that are not in the 'discontinued' category active_products = Product.objects.exclude(category='discontinued')

exclude() is also lazy. You can combine filter() and exclude() to build complex queries:

# Products with price > 100 and not in the 'clearance' category result = Product.objects.filter(price__gt=100).exclude(category='clearance')

Each call returns a new QuerySet, so you can chain as many as needed without affecting the original.

Creating Records with create and save

The create() method is a convenience that creates and saves an object in one step. It returns the saved instance.

product = Product.objects.create(name='Widget', price=19.99)

Equivalent to:

product = Product(name='Widget', price=19.99) product.save()

Use save() when you need to perform additional logic before saving, such as setting a field based on another value or validating custom constraints. create() does not call the model's save() method; it directly inserts the row.

When creating multiple objects, bulk_create() is significantly faster than calling create() in a loop, because it uses a single SQL INSERT statement.

products = [Product(name=f'Product {i}', price=i) for i in range(100)] Product.objects.bulk_create(products)

Updating Records with update and save

To update a single instance, modify its attributes and call save():

product = Product.objects.get(id=1) product.price = 24.99 product.save()

The update() method on a QuerySet performs a bulk update without loading each object into Python. It returns the number of rows affected.

updated = Product.objects.filter(category='clearance').update(price=0)

update() does not call save() on individual models, so signals and custom save() logic are not triggered. Use it for simple field updates that do not require model-level processing.

For bulk updates that need to call save() or handle per-row logic, iterate over the queryset and call save() individually, but be aware of the performance cost.

Deleting Records with delete

Call delete() on a model instance to remove that row:

product = Product.objects.get(id=1) product.delete()

Call delete() on a QuerySet to delete all matching rows in one database operation:

Product.objects.filter(category='discontinued').delete()

The delete() method returns a dictionary mapping object types to the number of deleted objects, including cascaded deletions. By default, Django emulates the ON DELETE CASCADE behavior of the database, so related objects are also deleted unless you override it with on_delete=models.PROTECT or similar.

Chaining Queries and Using Q Objects

filter() and exclude() accept keyword arguments that are combined with AND. To express OR conditions, use Q objects from django.db.models.

from django.db.models import Q # Products with price > 100 OR category = 'premium' result = Product.objects.filter(Q(price__gt=100) | Q(category='premium'))

You can also negate a Q object with ~ to achieve complex exclusions:

# Products that are not (price > 100 AND category = 'premium') result = Product.objects.exclude(Q(price__gt=100) & Q(category='premium'))

Chaining filter() and exclude() with Q objects keeps the query readable and avoids multiple round trips to the database.

Performance and Operational Considerations

When working with related models, use select_related() for foreign keys and prefetch_related() for many-to-many and reverse relations to avoid the N+1 query problem.

# Without select_related, each order triggers a query for its customer orders = Order.objects.select_related('customer').all()

For bulk operations, prefer bulk_create() and bulk_update() over individual save() calls. bulk_update() updates multiple rows with a single UPDATE statement:

products = Product.objects.filter(category='clearance') for product in products: product.price = 0 Product.objects.bulk_update(products, ['price'])

Transactions are important when performing multiple related operations. Use transaction.atomic() to ensure all changes are committed or rolled back together.

from django.db import transaction with transaction.atomic(): order = Order.objects.create(customer=customer) for item in items: OrderItem.objects.create(order=order, **item)

Finally, remember that filter() and exclude() are lazy, so you can build a query step by step without hitting the database until you evaluate it. This allows you to conditionally add filters based on user input without duplicating code. Understanding these methods and their performance implications will help you write scalable Django applications.

python django filter get exclude create update and delete: P | RYUSLOG DEV