Django Tips:

Advanced Django Tips

Q Objects for Complex Queries:

Example models.

from django.db import models


class Ticker(models.Model):
    symbol = models.CharField(max_length=50, unique=True)


class TickerPrice(models.Model):
    ticker = models.ForeignKey(
        Ticker, on_delete=models.CASCADE, related_name="ticker_prices"
    )
    price = models.DecimalField(max_digits=7, decimal_places=2)
    close_date = models.DateField()

Q objects can be combined together with &, representing AND, or |, representing OR. Let’s look at an example query.

today_and_yesterday_prices = TickerPrice.objects.filter(
    models.Q(close_date=today) | models.Q(close_date=yesterday)
)

# Fetching the ticker prices with close dates of today or yesterday.

today_and_yesterday_greater_than_1000 = TickerPrice.objects.filter(
    models.Q(price__gt=1000),
    (models.Q(close_date=today) | models.Q(close_date=yesterday)),
)

# Getting all prices with a close date of today or yesterday
# with a price greater than 1000


today_and_yesterday_greater_than_1000_without_BRK = (
    TickerPrice.objects.filter(
        models.Q(price__gt=1000),
        ~models.Q(ticker__symbol__startswith="BRK"),
        (models.Q(close_date=today) | models.Q(close_date=yesterday)),
    )
)

# Fetching all ticker prices greater than 1000 that don’t start
# with BRK with close dates of either today or yesterday. 
# We added the condition that the ticker’s symbol does not start with BRK

Optimize Database Calls with Prefetch Related and Select Related. We use prefetch related when we want to fetch a reverse foreign key or a many to many relationship. We use select related when we want to fetch a foreign key or a one to one relationship.

Annotate Querysets to Fetch Specific Values

Annotating a queryset enables us to add attributes to each object in the queryset. Annotations can be a reference to a value on the model or related model or an expression such as a sum or count.

This queryset fetches all the tickers and annotates each ticker object with a latest_price attribute. The latest price comes from the most recent related ticker price. The OuterRef allows us to reference the primary key of the ticker object. We use order_by to get the most recent price and use values to select only the price. Finally, the [:1] ensures we retrieve only one TickerPrice object.

Prefetch objects enable Django developers to control the operation of prefetch related. When we pass in a string argument to prefetch related, we’re saying fetch all of the related objects. A prefetch object lets us pass in a custom queryset to fetch a subset of the related objects.

Define Custom Query Sets and Model Managers for Code Reuse

Custom model managers and custom querysets let Django developers add extra methods to or modify the initial queryset for a model. Using these promotes the “don’t repeat yourself” (DRY) principle in software development and promotes reuse of common queries.

In the above code, we’ve created a custom queryset with some of the previously demonstrated queries as methods. We added this new queryset to our custom manager and overrode the default objects manager on the Ticker model with our custom manager. With the custom manager and queryset, we can do the following.

Instead of having to write the actual query for each of these examples, we call the methods defined in the custom queryset. This is especially useful if we use these queries in multiple places throughout the codebase.

Use of functools.partial in Django

Creating many upload_to callables for FileFields

transaction.on_commit() callbacks

Database functions

Last updated