Сигнал pre_init

Сигнал pre_init отправляется перед тем, как Django вызывает метод __init__ модели. Это позволяет выполнить пользовательский код до того, как экземпляр модели будет полностью инициализирован. Сигнал принимает аргументы: sender - класс модели, args - позиционные аргументы, переданные в конструктор, и kwargs - именованные аргументы. Сигнал полезен для логирования, валидации или изменения данных перед созданием объекта.

Синтаксис

pythonfrom django.db.models.signals import pre_init
from django.dispatch import receiver

@receiver(pre_init, sender=MyModel)
def my_handler(sender, *args, **kwargs):
  # Действия до инициализации
  pass

Пример

Давайте залогируем процесс инициализации модели Article:

pythonfrom django.db import models
from django.db.models.signals import pre_init
from django.dispatch import receiver
import logging

logger = logging.getLogger(__name__)

class Article(models.Model):
  title = models.CharField(max_length=100)
  content = models.TextField()
  created_at = models.DateTimeField(auto_now_add=True)

@receiver(pre_init, sender=Article)
def log_init(sender, *args, **kwargs):
  logger.info(f"Initializing {sender.__name__} with args: {args}, kwargs: {kwargs}")

# При создании объекта будет вызван сигнал
article = Article(title="New Article", content="Some content")

Результат выполнения кода:

python"Initializing Article with args: (), kwargs: {'title': 'New Article', 'content': 'Some content'}"

Пример

Изменим данные перед инициализацией модели User:

pythonfrom django.db import models
from django.db.models.signals import pre_init
from django.dispatch import receiver

class User(models.Model):
  username = models.CharField(max_length=50)
  email = models.EmailField()
  is_active = models.BooleanField(default=True)

@receiver(pre_init, sender=User)
def modify_init_data(sender, *args, **kwargs):
  if 'username' in kwargs:
    kwargs['username'] = kwargs['username'].lower()
  if 'email' in kwargs:
    kwargs['email'] = kwargs['email'].lower()

# Создание объекта с данными в верхнем регистре
user = User(username="JohnDoe", email="JOHN@EXAMPLE.COM")
print(user.username)
print(user.email)

Результат выполнения кода:

python"johndoe"
"john@example.com"

Пример

Проверим наличие обязательных полей перед инициализацией модели Product:

pythonfrom django.db import models
from django.db.models.signals import pre_init
from django.dispatch import receiver

class Product(models.Model):
  name = models.CharField(max_length=100)
  price = models.DecimalField(max_digits=10, decimal_places=2)
  stock = models.IntegerField()

@receiver(pre_init, sender=Product)
def validate_required_fields(sender, *args, **kwargs):
  required = ['name', 'price', 'stock']
  missing = [field for field in required if field not in kwargs]
  if missing:
    raise ValueError(f"Missing required fields: {missing}")

try:
  product = Product(name="Laptop", price=999.99)
except ValueError as e:
  print(e)

Результат выполнения кода:

python"Missing required fields: ['stock']"

Смотрите также

  • сигнал post_init,
    отправляемый после завершения инициализации модели
  • сигнал pre_save,
    отправляемый перед сохранением объекта в базу данных
  • сигнал post_save,
    отправляемый после сохранения объекта в базу данных
  • метод save,
    сохраняющий объект модели в базе данных