What is __(Double Underscore)?

In Django, __(double underscore) is used when writing database queries through relational fields between models. In simple terms, it is used to access fields connected to other tables or to filter data with specific conditions.

For instance, when two or more models are connected via relationships like ForeignKey or OneToOneField, you can access the desired fields through that relationship. Here, __ acts as a "linking chain," allowing you to access fields from different models in a connected way.

Example: Using __ in Model Relationships

Let's take a simple example. Suppose the Profile model is linked to the User model, and the user model has a field called username. We can filter specific profiles based on the username of the User model from the Profile model.

Model Definition:

from django.db import models
from django.contrib.auth.models import AbstractUser

class CustomUser(AbstractUser):
    pass

class Profile(models.Model):
    user = models.OneToOneField(CustomUser, on_delete=models.CASCADE)
    bio = models.TextField()

In the example above, the Profile model has a 1:1 relationship with CustomUser. Now let’s see how to access the fields of CustomUser from Profile using __.

Query using __:

# Filtering Profile objects based on CustomUser's username
profiles = Profile.objects.filter(user__username='jesse')

Here, user__username is key. user is the field connected to CustomUser in the Profile model, and to access the username of that field, we use __ to connect them. This way, we can retrieve data from the Profile model based on the username field of CustomUser.

Diverse Applications of __

__ is commonly used not just for accessing fields but also for imposing conditions. Django provides several filtering features to set various conditions in querysets, and most of them are implemented through __. Commonly used conditions include:

  • exact: Finds values that match exactly. (This is the default and can be omitted)
  • icontains: Finds values that are included, case-insensitively.
  • gt, lt, gte, lte: Conditions for greater than or less than values.
  • startswith, endswith: Finds values that start or end with a specific string.

Example: Various Filter Conditions

# Retrieving all profiles where CustomUser's email contains 'gmail.com'
profiles_with_gmail = Profile.objects.filter(user__email__icontains='gmail.com')

# Retrieving profiles where CustomUser's ID is greater than 10
profiles_with_id_gt_10 = Profile.objects.filter(user__id__gt=10)

# Retrieving profiles where CustomUser's username starts with 'jesse'
profiles_starting_with_jesse = Profile.objects.filter(user__username__startswith='jesse')

Accessing Multiple Relationship Fields via __

One of the strongest features of Django is the ability to navigate through multiple relationships using __ even when several models are connected. For example, consider a situation where an Order model is linked to Profile, and Profile is again connected to CustomUser.

Example of Multiple Relationship Models:

class Order(models.Model):
    profile = models.ForeignKey(Profile, on_delete=models.CASCADE)
    order_date = models.DateTimeField()
    amount = models.DecimalField(max_digits=10, decimal_places=2)

Now, let's assume we want to retrieve data from Order based on the username of CustomUser.

Filtering Multiple Relationships:

# Retrieving orders for CustomUser with username 'jesse'
orders_for_user = Order.objects.filter(profile__user__username='jesse')

Here, we can access the fields of CustomUser through multiple layers of relationships using profile__user__username. This connects the relationships from OrderProfileCustomUser, thereby allowing for simple filtering.

Summary

  • __ is used to reference fields following relationships between models.
  • Filtering data by setting various query conditions is possible.
  • Handling complex queries can be simplified by connecting fields of multiple relationships.

Now that you understand the role and usage of __, you will be able to write more powerful queries in Django ORM. By considering the relational structure of the database and appropriately utilizing this symbol, you can handle efficient data processing and simplify complex relationships.