Django ORMでのシグナルとハンドラの設定方法

PythonのDjangoフレームワークには、特定のイベントが発生したときに特定のコードを実行するための仕組みとして「シグナル」と「ハンドラ」があります。この記事では、Django ORMでのシグナルとハンドラの設定について、具体的なコード例とその詳細解説、さらには応用例を含めてご紹介します。

目次

シグナルとは?

シグナルは、特定のイベントが発生した際に通知を行う仕組みです。例えば、モデルの保存処理が完了したときや、ユーザーがログインしたときなどにコードを実行したい場合に使用します。

基本的な使い方

Djangoにはいくつかの組み込みシグナルがありますが、独自にシグナルを定義することも可能です。基本的な使い方は以下のようになります。

from django.db.models.signals import pre_save
from django.dispatch import receiver
from my_app.models import MyModel

# ハンドラ関数の定義
@receiver(pre_save, sender=MyModel)
def my_handler(sender, **kwargs):
    print('MyModel is about to be saved.')

ハンドラとは?

ハンドラは、シグナルが発火したときに実行される関数です。上記の例では`my_handler`がハンドラになります。

ハンドラの設定

`@receiver`デコレータを使って、どのシグナルに対してどのハンドラを実行するかを定義します。以下はその例です。

@receiver(pre_save, sender=MyModel)
def another_handler(sender, **kwargs):
    print('Another action.')

具体的な例と解説

以下に具体的なコード例とその解説を示します。ここでは、`UserProfile`モデルが保存される前に、何らかの処理を行いたいと考えています。

from django.db.models.signals import pre_save
from django.dispatch import receiver
from my_app.models import UserProfile

@receiver(pre_save, sender=UserProfile)
def profile_pre_save(sender, instance, **kwargs):
    # instanceには保存されるUserProfileオブジェクトが渡される
    instance.full_name = instance.first_name + ' ' + instance.last_name

この例では、`UserProfile`モデルが保存される前に`profile_pre_save`ハンドラが呼ばれ、`first_name`と`last_name`を結合して`full_name`を更新しています。

応用例1: メール送信

UserProfileが更新された際に、ユーザーにメールを送る例です。

from django.core.mail import send_mail

@receiver(pre_save, sender=UserProfile)
def send_email_to_user(sender, instance, **kwargs):
    send_mail(
        'Your profile was updated',
        'Your profile was recently updated.',
        'from@example.com',
        [instance.email],
        fail_silently=False,
    )

応用例2: ロギング

UserProfileが保存される際に、その情報をログに記録する例です。

import logging

@receiver(pre_save, sender=UserProfile)
def log_profile_update(sender, instance, **kwargs):
    logger = logging.getLogger(__name__)
    logger.info(f'UserProfile updated: {instance.full_name}')

まとめ

Django ORMでのシグナルとハンドラの設定は、様々なイベントに柔軟に対応する強力な仕組みです。上記の例を参考に、自分のプロジェクトに適用してみてください。

コメント

コメントする

目次