← Назад к вопросам
Как создать объект в Django ORM?
1.0 Junior🔥 211 комментариев
#Django#Базы данных (SQL)
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Создание объектов в Django ORM
Django ORM (Object-Relational Mapping) позволяет взаимодействовать с БД через Python объекты вместо сырого SQL. Это делает код безопаснее и удобнее.
Основные способы создания объектов
1. Использование метода create()
Самый простой способ — сразу сохранить в БД:
# models.py
from django.db import models
class User(models.Model):
name = models.CharField(max_length=100)
email = models.EmailField(unique=True)
age = models.IntegerField(null=True, blank=True)
created_at = models.DateTimeField(auto_now_add=True)
# views.py
from .models import User
# Способ 1: create() — сразу сохраняет
user = User.objects.create(
name="Alice",
email="alice@example.com",
age=25
)
# user.id уже установлен! Объект в БД.
print(user.id) # 1
print(user.created_at) # 2024-01-15 10:30:00
2. Инстанцирование + save()
Если нужно проверить или изменить объект перед сохранением:
# Шаг 1: создаём объект в памяти (БЕЗ сохранения)
user = User(
name="Bob",
email="bob@example.com",
age=30
)
print(user.id) # None — ещё не в БД
# Шаг 2: проверяем данные
if user.age < 18:
raise ValueError("User must be 18+")
# Шаг 3: сохраняем в БД
user.save()
print(user.id) # 2 — теперь в БД!
3. get_or_create()
Получить объект или создать если его нет:
# Возвращает кортеж (объект, был_ли_создан)
user, created = User.objects.get_or_create(
email="charlie@example.com",
defaults={
'name': 'Charlie',
'age': 28
}
)
if created:
print(f"Создан новый пользователь: {user.name}")
else:
print(f"Пользователь уже существует: {user.name}")
# Полезно для:
# - Импорта данных (не дублировать)
# - Кэширования (создать если нет)
# - Конфигурации (create default settings)
4. update_or_create()
Обновить если существует, иначе создать:
user, created = User.objects.update_or_create(
email="dave@example.com", # Ищем по этому полю
defaults={
'name': 'Dave',
'age': 32
}
)
if created:
print("Создан новый объект")
else:
print("Объект обновлён")
Работа с related объектами
Foreign Key
# models.py
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
bio = models.TextField(blank=True)
avatar = models.ImageField(upload_to='avatars/')
class Post(models.Model):
author = models.ForeignKey(User, on_delete=models.CASCADE)
title = models.CharField(max_length=200)
content = models.TextField()
# views.py
# Способ 1: передать объект
user = User.objects.get(id=1)
post = Post.objects.create(
author=user, # Передаём объект
title="My Post",
content="Content here"
)
# Способ 2: передать ID
post = Post.objects.create(
author_id=1, # Передаём ID
title="Another Post",
content="More content"
)
# Способ 3: сначала create потом связать
post = Post(title="Draft", content="Drafting...")
post.author = user
post.save()
Many-to-Many
class Tag(models.Model):
name = models.CharField(max_length=50)
class Article(models.Model):
title = models.CharField(max_length=200)
tags = models.ManyToManyField(Tag)
# Создание объектов
article = Article.objects.create(title="Django Tips")
# Добавление связей
tag1 = Tag.objects.create(name="Django")
tag2 = Tag.objects.create(name="Python")
article.tags.add(tag1, tag2) # Добавить множество
# или
article.tags.add(1, 2) # По ID
# Удаление связей
article.tags.remove(tag1)
# Очистка всех связей
article.tags.clear()
# Проверка наличия
if tag1 in article.tags.all():
print("Tag exists")
Bulk операции
bulk_create() — создание множества объектов
# ПЛОХО: сто запросов в БД
for i in range(1000):
User.objects.create(name=f"User{i}", email=f"user{i}@example.com")
# ХОРОШО: один запрос
users = [
User(name=f"User{i}", email=f"user{i}@example.com")
for i in range(1000)
]
User.objects.bulk_create(users, batch_size=100)
# Параметры:
# batch_size — сколько объектов в одном батче
# ignore_conflicts — игнорировать дубликаты (для UNIQUE полей)
# С ignore_conflicts для БД которая их поддерживает
User.objects.bulk_create(
users,
batch_size=100,
ignore_conflicts=True
)
bulk_update() — обновление множества объектов
# Получить объекты
users = User.objects.filter(age__lt=18)
# Изменить их
for user in users:
user.age = 18
# ПЛОХО: сто запросов
for user in users:
user.save()
# ХОРОШО: один запрос
User.objects.bulk_update(users, ['age'], batch_size=100)
Валидация перед сохранением
Использование clean() и full_clean()
# models.py
from django.core.exceptions import ValidationError
class User(models.Model):
email = models.EmailField()
age = models.IntegerField()
def clean(self):
if self.age < 0:
raise ValidationError("Age cannot be negative")
if self.age > 150:
raise ValidationError("Age seems unrealistic")
# views.py
user = User(name="Alice", age=-5)
# Валидация через clean()
try:
user.full_clean() # Запускает валидацию
except ValidationError as e:
print(f"Validation error: {e}")
# Сохранение ТОЛЬКО если валидно
try:
user.full_clean()
user.save()
except ValidationError as e:
print(f"Cannot save: {e}")
Использование Forms для валидации
# forms.py
from django import forms
from .models import User
class UserForm(forms.ModelForm):
class Meta:
model = User
fields = ['name', 'email', 'age']
def clean_email(self):
email = self.cleaned_data['email']
if User.objects.filter(email=email).exists():
raise forms.ValidationError("Email already exists")
return email
# views.py
form = UserForm(data={'name': 'Bob', 'email': 'bob@example.com', 'age': 25})
if form.is_valid():
user = form.save() # Создаёт и сохраняет
else:
print(form.errors)
Сигналы при создании
post_save сигнал
# signals.py
from django.db.models.signals import post_save
from django.dispatch import receiver
from .models import User, Profile
@receiver(post_save, sender=User)
def create_user_profile(sender, instance, created, **kwargs):
"""Автоматически создай Profile когда создан User"""
if created: # Только при создании, не при обновлении
Profile.objects.create(user=instance)
# apps.py
from django.apps import AppConfig
class MyAppConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'myapp'
def ready(self):
import myapp.signals # Загружаем сигналы
# settings.py
INSTALLED_APPS = [
'myapp.apps.MyAppConfig', # Используем AppConfig
]
Обработка ошибок при создании
from django.db import IntegrityError
try:
user = User.objects.create(
name="Eve",
email="existing@example.com" # Уже существует!
)
except IntegrityError as e:
print(f"Ошибка БД (может быть UNIQUE constraint): {e}")
# Или проверь перед созданием
if User.objects.filter(email="test@example.com").exists():
print("User already exists")
else:
user = User.objects.create(email="test@example.com")
Лучшие практики
✅ Делай так:
# 1. Используй create() для простых случаев
user = User.objects.create(name="Alice", email="alice@example.com")
# 2. Используй bulk_create() для множества объектов
users = [User(name=f"User{i}") for i in range(1000)]
User.objects.bulk_create(users, batch_size=100)
# 3. Валидируй перед сохранением
user = User(name="Bob", age=-5)
try:
user.full_clean()
user.save()
except ValidationError as e:
print(f"Invalid: {e}")
# 4. Используй get_or_create() для предотвращения дубликатов
user, created = User.objects.get_or_create(
email="test@example.com",
defaults={'name': 'Test'}
)
# 5. Используй сигналы для побочных эффектов
@receiver(post_save, sender=User)
def do_something(sender, instance, created, **kwargs):
if created:
# Выполни что-то при создании
pass
❌ Не делай так:
# 1. Не используй save() в цикле (медленно!)
for i in range(1000):
user = User(name=f"User{i}")
user.save() # ПЛОХО!
# 2. Не забывай валидацию
user = User(age=-5)
user.save() # ОПАСНО! Невалидные данные в БД
# 3. Не используй сырой SQL где можно ORM
from django.db import connection
cursor = connection.cursor()
cursor.execute("INSERT INTO app_user (name, email) VALUES (%s, %s)", [...])
# ПЛОХО! Потеря типизации и безопасности
# 4. Не путай create() и save()
create() # СРАЗУ в БД
save() # Сохранить ПОСЛЕ изменения
Заключение
Создание объектов в Django ORM — это основной навык:
- create() — сразу в БД
- save() — после инстанцирования
- get_or_create() — без дубликатов
- update_or_create() — обновить или создать
- bulk_create() — много объектов
- Валидация — всегда проверяй данные
- Сигналы — для побочных эффектов
Выбирай правильный инструмент для задачи!