← Назад к вопросам

Как создать объект в 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() — много объектов
  • Валидация — всегда проверяй данные
  • Сигналы — для побочных эффектов

Выбирай правильный инструмент для задачи!