Каково назначение двойного подчеркивания (__) в Django

«Каково назначение двойного подчеркивания (__) в Django» — вопрос из категории Django, который задают на 10% собеседований Python Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

В Django двойное подчеркивание (__) используется в двух ключевых, но совершенно разных контекстах:

1. Lookups в QuerySet API

Это основное, специфичное для Django применение. Двойное подчеркивание используется для построения сложных запросов к базе данных, разделяя имя поля и тип поиска (lookup) или для навигации по связанным моделям.

Основные случаи использования:

  • Переход по связанным моделям (Foreign Key, ManyToMany): Post.objects.filter(author__name='John Doe') — фильтрация постов по имени связанного автора.
  • Указание типа сравнения поля: Post.objects.filter(views__gte=1000)gte (greater than or equal) означает "больше или равно". User.objects.filter(email__icontains='@example.com')icontains означает "содержит без учета регистра".
  • Работа с датами и временем: Post.objects.filter(pub_date__year=2023) — фильтрация по году публикации.

Пример:

from django.db import models

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

class Post(models.Model):
    title = models.CharField(max_length=200)
    author = models.ForeignKey(Author, on_delete=models.CASCADE)
    views = models.PositiveIntegerField(default=0)

# Найти все посты автора с именем, начинающимся на 'John',
# и у которых более 1000 просмотров.
posts = Post.objects.filter(
    author__name__startswith='John',
    views__gte=1000
)

2. "Магические" методы Python (Dunder Methods)

Как и в стандартном Python, Django использует dunder-методы (double underscore) для определения специального поведения объектов. Это не является уникальной особенностью фреймворка.

Пример в модели Django:

class Post(models.Model):
    title = models.CharField(max_length=200)

    def __str__(self):
        # Определяет строковое представление объекта,
        # которое используется, например, в админ-панели Django.
        return self.title