Django ORM
monoteistDjango ORM (Object-Relational Mapping) — мощный инструмент, который позволяет взаимодействовать с базой данных, используя Python-код вместо SQL-запросов. Это значительно упрощает разработку, абстрагируя сложности работы с базами данных. Расскажу подробно о каждом аспекте:
1. Основные понятия и работа с моделями
Создание модели
Модель — это Python-класс, который наследуется от django.db.models.Model. Каждый атрибут класса соответствует полю таблицы в базе данных.
Пример:
from django.db import models
class Author(models.Model):
name = models.CharField(max_length=100)
age = models.IntegerField()
Поля модели:
- CharField: для строк (ограничение
max_lengthобязательно). - IntegerField: для целых чисел.
- TextField: для длинных текстов.
- BooleanField: для
True/False. - DateField, DateTimeField: для работы с датами и временем.
- ForeignKey: связь "один ко многим".
- ManyToManyField: связь "многие ко многим".
- OneToOneField: связь "один к одному".
Метаданные модели
Внутренний класс Meta задаёт настройки модели:
class Author(models.Model):
name = models.CharField(max_length=100)
class Meta:
db_table = 'authors' # Имя таблицы в БД
ordering = ['name'] # Сортировка по умолчанию
2. Управление миграциями
Миграции — механизм, который синхронизирует модели с базой данных.
Создание миграции:bash python manage.py makemigrations Применение миграций:bash python manage.py migrate
Изменения моделей:
Если вы изменили модель, всегда создавайте миграции. Не меняйте структуру таблиц вручную, это нарушит синхронизацию.
3. CRUD-операции (создание, чтение, обновление, удаление)
Создание записи
author = Author(name="John Doe", age=30) author.save() # Или через метод create(): Author.objects.create(name="Jane Smith", age=25)
Чтение записей
- Все записи:
authors = Author.objects.all()
- Фильтрация:
authors = Author.objects.filter(age__gte=30) # Возраст >= 30
- Получение одной записи:
author = Author.objects.get(id=1)
- ⚠️ Используйте
getтолько если точно уверены, что запись есть в базе данных (иначе будет ошибка). Можно использоватьget_object_or_404 - Агрегации:
from django.db.models import Count, Avg
avg_age = Author.objects.aggregate(Avg('age'))
Обновление записи
author = Author.objects.get(id=1) author.age = 35 author.save()
Или массовое обновление:
Author.objects.filter(age__lt=30).update(age=30)
Удаление записи
author = Author.objects.get(id=1) author.delete()
Массовое удаление:
Author.objects.filter(age__lt=30).delete()
4. Связи между моделями
ForeignKey (один ко многим)
class Book(models.Model):
title = models.CharField(max_length=100)
author = models.ForeignKey(Author, on_delete=models.CASCADE)
Пример использования:
book = Book.objects.create(title="My Book", author=author)
ManyToManyField (многие ко многим)
class Publisher(models.Model):
name = models.CharField(max_length=100)
class Book(models.Model):
title = models.CharField(max_length=100)
publishers = models.ManyToManyField(Publisher)
Добавление связи:
publisher = Publisher.objects.create(name="Publisher A") book.publishers.add(publisher)
5. Запросы: фильтрация, аннотации, агрегации
Фильтрация
exact: точное совпадение.contains: содержит.startswith,endswith: начало/окончание строки.in: значение в списке.gte,lte: больше/меньше или равно.
Пример:
Author.objects.filter(name__contains="John", age__gte=30)
Аннотации
Добавление вычисляемых полей:
from django.db.models import Count
authors = Author.objects.annotate(book_count=Count('book'))
6. Тонкости производительности
- Жадные запросы:Используйте
select_relatedдля ForeignKey. - Используйте
prefetch_relatedдля ManyToManyField.
Пример:
books = Book.objects.select_related('author').all()
- Количество запросов: Проверьте число запросов с помощью
django-debug-toolbar. - Транзакции: Для сложных операций используйте
atomic:
from django.db import transaction
with transaction.atomic():
# Ваши операции
7. Управление сложными запросами
Для более сложных SQL-запросов используйте Q-объекты и F-объекты.
Q-объекты (логические условия)
from django.db.models import Q authors = Author.objects.filter(Q(age__gte=30) | Q(name__startswith="J"))
F-объекты (сравнение полей)
from django.db.models import F
authors = Author.objects.filter(age__gte=F('book_count'))
8. Кастомизация менеджеров
Можно создать свои методы для запросов:
class AuthorManager(models.Manager):
def young_authors(self):
return self.filter(age__lt=30)
class Author(models.Model):
name = models.CharField(max_length=100)
age = models.IntegerField()
objects = AuthorManager()
Использование:
young_authors = Author.objects.young_authors()
9. Миграции и изменение схемы базы
Если вы изменяете существующую модель (например, добавляете новое поле), убедитесь, что:
- Новое поле имеет
defaultилиnull=True. - Убедитесь, что нет данных, которые могут вызвать ошибку.
10. Сигналы Django
Позволяют реагировать на события, например, создание записи:
from django.db.models.signals import post_save
from django.dispatch import receiver
@receiver(post_save, sender=Author)
def notify_author_created(sender, instance, created, **kwargs):
if created:
print(f"Author {instance.name} created")
11. Ограничения Django ORM
- Django ORM может быть медленнее, чем сырой SQL, для сложных запросов.
- Ограниченная поддержка операций с большим объёмом данных.
- Некоторые сложные запросы (например, CTE) сложнее реализовать.