Сигнал pre_init
Сигнал pre_init отправляется перед тем, как Django вызывает метод __init__ модели. Это позволяет выполнить пользовательский код до того, как экземпляр модели будет полностью инициализирован. Сигнал принимает аргументы: sender - класс модели, args - позиционные аргументы, переданные в конструктор, и kwargs - именованные аргументы. Сигнал полезен для логирования, валидации или изменения данных перед созданием объекта.
Синтаксис
from 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:
from 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")
Результат выполнения кода:
"Initializing Article with args: (), kwargs: {'title': 'New Article', 'content': 'Some content'}"
Пример
Изменим данные перед инициализацией модели User:
from 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)
Результат выполнения кода:
"johndoe"
"john@example.com"
Пример
Проверим наличие обязательных полей перед инициализацией модели Product:
from 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)
Результат выполнения кода:
"Missing required fields: ['stock']"