Discover the Power of Django ORM: A Guide to Database Interactions with a Queries Cheat Sheet

Jan. 4, 2024


0
6 min read
1.04K

Django's Object-Relational Mapping (ORM) is a cornerstone in simplifying database interactions, offering a Pythonic layer to seamlessly manage databases. This guide aims to delve into Django's ORM intricacies, encompassing CRUD operations, querying, model relationships, aggregation, raw SQL execution, and data retrieval from multiple related tables.

Setting Up Models

from django.db import models

class Author(models.Model):
    name = models.CharField(max_length=100)
    email = models.EmailField()

class Book(models.Model):
    title = models.CharField(max_length=200)
    author = models.ForeignKey(Author, on_delete=models.CASCADE)
    published_date = models.DateField()

Explanation:

This code snippet defines two Django models: Author and Book. The Author model has fields for name and email, while the Book model has fields for title, author (a foreign key referencing Author), and published_date.

The Author model includes a CharField for the author's name limited to 100 characters and an EmailField for the author's email address. The Book model contains a CharField for the book's title (limited to 200 characters), a ForeignKey linking it to an Author (using on_delete=models.CASCADE, which means if an author is deleted, all associated books will be deleted), and a DateField for the published date of the book.

This setup allows you to create relationships between authors and books in your Django application.

CRUD Operations

Creating Records

new_author = Author.objects.create(name="John Doe", email="john@example.com")
new_book = Book.objects.create(title="Sample Book", author=new_author, published_date="2023-01-01")

Explanation:

The first line creates a new Author instance with the name "John Doe" and email "john@example.com". The second line creates a new Book instance titled "Sample Book", associates it with the previously created author (new_author), and sets the published date to January 1, 2023.

This code assumes you have Django models named Author and Book with appropriate fields like name, email, title, author, and published_date defined in your Django application.

Retrieving Records

all_authors = Author.objects.all()
author = Author.objects.get(id=1)
filtered_authors = Author.objects.filter(name__startswith='J')
recent_books = Book.objects.filter(published_date__gt='2023-01-01')

Explanation:

These are Django ORM queries for retrieving records from the defined models (Author and Book).

  1. all_authors = Author.objects.all()

    • Retrieves all records from the Author model.
  2. author = Author.objects.get(id=1)

    • Retrieves a specific Author record where the id is equal to 1. Note that using get() expects only one result and will throw an error if there's no record or more than one record matching the query.
  3. filtered_authors = Author.objects.filter(name__startswith='J')

    • Retrieves Author records where the name field starts with the letter 'J'. The __startswith is a lookup that filters records based on a specific condition.
  4. recent_books = Book.objects.filter(published_date__gt='2023-01-01')

    • Retrieves Book records where the published_date is greater than (later than) January 1, 2023. The __gt lookup is used to compare dates.

These queries showcase different ways to retrieve records using Django's ORM, including fetching all records, filtering based on specific conditions, and retrieving a single record by its unique identifier.

Updating and Deleting Records

author = Author.objects.get(id=1)
author.email = "new_email@example.com"
author.save()

author.delete()

Explanation:

 

  • Author.objects.get(id=1) retrieves an author with an ID of 1.
  • author.email = "new_email@example.com" updates the author's email.
  • author.save() saves the changes to the database.
  • author.delete() deletes the author record from the database.

Querying with Relationships

Retrieve Books by a Specific Author

author = Author.objects.get(name='John Doe')
books_by_author = author.book_set.all()

Explanation:

  • Author.objects.get(name='John Doe') retrieves the Author instance with the name 'John Doe'.
  • author.book_set.all() accesses all books associated with the retrieved author through the reverse relationship created by the ForeignKey. Django by default creates a related manager book_set to access related objects, which retrieves all books authored by 'John Doe'.

Retrieve Author of a Specific Book

book = Book.objects.get(title='Sample Book')
author_of_book = book.author

Explanation:

  • Book.objects.get(title='Sample Book') fetches the Book instance with the title 'Sample Book'.
  • book.author accesses the associated author instance for the retrieved book. The author attribute represents the ForeignKey relationship defined in the Book model.

These examples showcase how to navigate relationships between models in Django ORM, allowing retrieval of related objects effortlessly.

Advanced ORM Techniques

Aggregation and Annotation

from django.db.models import Count, Avg

authors_with_book_count = Author.objects.annotate(book_count=Count('book'))
average_books_per_author = Author.objects.aggregate(avg_books=Avg(Count('book')))

Explanation:

  • Author.objects.annotate(book_count=Count('book')) uses the annotate() method to add a calculated field book_count to each Author instance, counting the number of associated books for each author.
  • Author.objects.aggregate(avg_books=Avg(Count('book'))) employs the aggregate() method to calculate the average count of books per author across all authors.

These aggregation methods offer insights into the relationships and data distribution within the database, providing aggregated values based on related objects.

Django Queries Cheat Sheet

Create, Retrieve, Update, Delete (CRUD)

Create:

# Create a new instance
instance = ModelName.objects.create(field1=value1, field2=value2)

Retrieve:

# Retrieve all instances
all_instances = ModelName.objects.all()

# Retrieve a specific instance by primary key
instance = ModelName.objects.get(pk=primary_key_value)

# Filter instances based on conditions
filtered_instances = ModelName.objects.filter(field=value)

Update:

# Update a specific field in an instance
instance.field = new_value
instance.save()

Delete:

# Delete a specific instance
instance.delete()

Querying with Relationships

Access related objects:

# Retrieve related objects for a specific instance
related_objects = instance.related_model_set.all()

Retrieve related object from ForeignKey:

# Retrieve related object from a ForeignKey
related_instance = instance.foreign_key_field

Advanced Querying

Aggregation:

from django.db.models import Count, Avg

# Annotate query set with aggregated values
annotated_qs = ModelName.objects.annotate(count_field=Count('field'))

# Aggregate values across query set
aggregated_values = ModelName.objects.aggregate(avg_field=Avg('field'))

Chaining Filters:

# Chain multiple filters
filtered_qs = ModelName.objects.filter(field1=value1).filter(field2=value2)

Raw SQL Queries:

from django.db import connection

with connection.cursor() as cursor:
    cursor.execute("SELECT * FROM app_model WHERE condition = %s", [value])
    results = cursor.fetchall()

Conditional Filtering

Filtering with Conditions:

# Filter using conditions (AND)
qs = ModelName.objects.filter(field1=value1, field2=value2)

# Filter using OR conditions
qs = ModelName.objects.filter(Q(field1=value1) | Q(field2=value2))

Exclude Records:

# Exclude specific records
excluded_qs = ModelName.objects.exclude(field=value)

Ordering and Limiting

Ordering Results:

# Order query set by a specific field
ordered_qs = ModelName.objects.order_by('field')

# Reverse ordering
reversed_qs = ModelName.objects.order_by('-field')

Limit and Offset:

# Limit the number of results
limited_qs = ModelName.objects.all()[:5]

# Offset results
offset_qs = ModelName.objects.all()[5:10]

Existence Checks

Check Existence:

# Check if any records exist
exists = ModelName.objects.exists()

# Check existence based on condition
exists = ModelName.objects.filter(field=value).exists()

F Expressions and Aggregation

F Expressions (Direct Database References):

from django.db.models import F

# Update with F expression
ModelName.objects.filter(id=1).update(field=F('field') + 1)

Conditional Aggregation:

from django.db.models import Case, When, IntegerField, Sum

# Aggregate with conditions
total = ModelName.objects.aggregate(
    total_count=Sum(
        Case(
            When(field=value, then=1),
            default=0,
            output_field=IntegerField(),
        )
    )
)

Prefetch Related and Select Related

Prefetch Related Objects:

# Prefetch related objects to minimize database queries
qs = ModelName.objects.prefetch_related('related_model')

Select Related Objects: 

# Select related objects in a single query
qs = ModelName.objects.select_related('related_model')

This extended cheat sheet now covers more querying techniques in Django's ORM, including date filtering, case-insensitive filtering, handling null and not null values, aggregation with grouping, and executing raw SQL queries. Use this as a handy reference while working with Django's powerful ORM capabilities!

Conclusion

By utilizing Django's ORM and its querying capabilities with relationships, developers can effortlessly navigate and retrieve related objects, allowing for efficient data querying and manipulation within Django applications.

django CRUD ORM Queries Appreciate you stopping by my post! 😊

Add a comment


Note: If you use these tags, write your text inside the HTML tag.
Login Required