Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
# ForeignKey в Django
ForeignKey — это полевой тип в Django ORM, который создаёт связь один-ко-многим (one-to-many) между двумя моделями. Он хранит ссылку на первичный ключ связанного объекта.
Базовый синтаксис
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()
Здесь каждая книга (Book) связана с одним автором (Author). В БД это создаст колонку author_id, которая хранит id автора.
Параметр on_delete
Отвечает за поведение при удалении связанного объекта:
# CASCADE — удалить все связанные объекты
author = models.ForeignKey(Author, on_delete=models.CASCADE)
# SET_NULL — установить NULL (требует null=True)
author = models.ForeignKey(Author, on_delete=models.SET_NULL, null=True)
# SET_DEFAULT — установить значение по умолчанию
author = models.ForeignKey(Author, on_delete=models.SET_DEFAULT, default=1)
# PROTECT — запретить удаление (выбросить ошибку)
author = models.ForeignKey(Author, on_delete=models.PROTECT)
# DO_NOTHING — ничего не делать (может нарушить целостность)
author = models.ForeignKey(Author, on_delete=models.DO_NOTHING)
Использование в коде
# Создание объекта
author = Author.objects.create(name="Толстой", email="tolstoy@example.com")
book = Book.objects.create(
title="Война и мир",
author=author, # Можно передать объект
published_date="1869-01-01"
)
# Или через id
book = Book.objects.create(
title="Война и мир",
author_id=1, # Или через id
published_date="1869-01-01"
)
# Доступ к связанному объекту
print(book.author.name) # "Толстой"
print(book.author_id) # 1
Обратные связи (Reverse Relations)
# Получить все книги автора
author = Author.objects.get(id=1)
books = author.book_set.all()
# Или с кастомным именем (related_name)
class Book(models.Model):
title = models.CharField(max_length=200)
author = models.ForeignKey(
Author,
on_delete=models.CASCADE,
related_name='books' # Кастомное имя обратной связи
)
# Теперь используем
books = author.books.all()
# Фильтрация в обратном направлении
authors_with_published_books = Author.objects.filter(
books__published_date__year=2023
)
Параметры ForeignKey
author = models.ForeignKey(
Author, # Целевая модель
on_delete=models.CASCADE, # Поведение при удалении
related_name='books', # Имя для обратной связи
related_query_name='book', # Имя для фильтров
db_column='author_id', # Имя колонки (редко)
null=True, # Может ли быть NULL
blank=True, # Может ли быть пусто в форме
limit_choices_to={'active': True}, # Ограничить choices в админке
to_field='id' # На какое поле ссылаться (по умолчанию pk)
)
Оптимизация запросов
# Плохо: N+1 problem
for book in Book.objects.all():
print(book.author.name) # Запрос в БД для каждой книги
# Хорошо: select_related
for book in Book.objects.select_related('author'):
print(book.author.name) # Один запрос с JOIN
ForeignKey vs OneToOneField
# ForeignKey — один автор может иметь много книг
author = models.ForeignKey(Author, on_delete=models.CASCADE)
# OneToOneField — один автор, один профиль
author_profile = models.OneToOneField(AuthorProfile, on_delete=models.CASCADE)
Самореферентные связи
# Для дерева категорий, комментариев и т.п.
class Category(models.Model):
name = models.CharField(max_length=100)
parent = models.ForeignKey(
'self',
on_delete=models.SET_NULL,
null=True,
blank=True,
related_name='children'
)
# Использование
root = Category.objects.create(name="Электроника")
phones = Category.objects.create(name="Телефоны", parent=root)
Миграции
# Если добавили ForeignKey к существующей модели
# Django спросит значение для старых записей
# Либо используй default, либо null=True+blank=True
author = models.ForeignKey(
Author,
on_delete=models.CASCADE,
default=1 # Или null=True для пустого значения
)
Важные моменты
- Индексы — ForeignKey автоматически создаёт индекс в БД (ускоряет фильтры и JOIN)
- Целостность — БД проверяет, что ссылаемый объект существует
- Производительность — используй
select_related()для оптимизации - Каскадное удаление — внимательнее с
CASCADE, может удалить неожиданно много данных - Обратные запросы — используй
related_nameдля читаемости кода
ForeignKey — это основа реляционных моделей в Django. Правильное использование критично для целостности и производительности приложения.