Django
信号
サーチ…
パラメーター
クラス/メソッド | なぜ |
---|---|
UserProfile()クラス | UserProfileクラスは、 Djangoのデフォルトユーザーモデルを拡張します 。 |
create_profile()メソッド | create_profile()メソッドは、Django Userモデルのpost_save シグナルが解放されるたびに実行されます。 |
備考
今、詳細。
Djangoシグナルは、発生時に特定のタスク(保存前または保存後のモデルや削除など)をアプリに通知する方法です。
これらの信号を使用すると、信号がリリースされた直後に選択したアクションを実行できます。
例えば、 いつでも新しい Djangoのユーザーが作成され、ユーザーモデルは、以下のような関連付けのparamsで、信号を放出しsender=User
、あなたが特にこの場合には、発生した特定の活動への信号のリスニングをターゲットにすることができ、新しいユーザーの作成。
上記の例では、Userオブジェクトが作成された直後に、UserProfileオブジェクトを作成することを意図しています。したがって、 User
モデル(デフォルトのDjango User Model)からのpost_save
信号をpost_save
聞くことによって、新しいUser
が作成された直後にUserProfile
オブジェクトを作成します。
Djangoドキュメンテーションは、 利用可能なすべての可能なシグナルに関する豊富なドキュメントを提供しています 。
しかし、上記の例は、信号を使用することが有用な追加となる典型的な使用例を実際に説明することです。
「大きな力をもって、大きな責任を負う」彼らが素晴らしいのだからあなたのアプリケーションやプロジェクト全体に信号を散らばってしまうことが魅力的かもしれません。まあ、しないでください。彼らはクールだから、心に浮かぶすべての簡単な状況のための解決策にはなりません。
信号は、いつものように、すべてではありません。ログイン/ログアウト、信号は素晴らしいです。ユーザーモデルなどの兆候を放つ主要モデル。
あなたのアプリケーションのすべてのモデルのためのシグナルを作成することは、ある時点で圧倒され、Djangoシグナルのスパースな使用のアイデアを全面的に打ち負かします。
Djangoの2つのスクープに基づいてシグナルを使用しないでください :
- シグナルは特定の1つのモデルに関連し、そのモデルのメソッドの1つに移動できます。おそらく
save()
によって呼び出されsave()
。 - この信号は、カスタムモデルマネージャメソッドで置き換えることができます。
- 信号は特定のビューに関連し、そのビューに移動できます
次の場合に信号を使用しても問題ありません。
- 信号受信機は、複数のモデルに変更を加える必要があります。
- 同じ信号を複数のアプリから送信し、共通の受信機で同じ方法で処理したいとします。
- モデルの保存後にキャッシュを無効にしたいとします。
- あなたはコールバックを必要とする珍しいシナリオがあり、シグナルを使用する以外にそれを処理する他の方法はありません。たとえば、サードパーティアプリケーションのモデルの
save()
またはinit()
に基づいて何かをトリガーしたいとします。サードパーティのコードを変更することはできません。拡張が不可能な場合もあります。したがって、シグナルがコールバックのトリガーとなります。
ユーザプロファイルの拡張例
この例は、Proのような拡張Djangoユーザプロファイルから抜粋したスニペットです
from django.db import models
from django.contrib.auth.models import User
from django.db.models.signals import post_save
class UserProfile(models.Model):
user = models.OneToOneField(User, related_name='user')
website = models.URLField(default='', blank=True)
bio = models.TextField(default='', blank=True)
def create_profile(sender, **kwargs):
user = kwargs["instance"]
if kwargs["created"]:
user_profile = UserProfile(user=user)
user_profile.save()
post_save.connect(create_profile, sender=User)
シグナルを送信/送信するための異なる構文
from django.db import models
from django.contrib.auth.models import User
from django.db.models.signals import post_save
from django.dispatch import receiver
class UserProfile(models.Model):
user = models.OneToOneField(User, related_name='user')
website = models.URLField(default='', blank=True)
bio = models.TextField(default='', blank=True)
@receiver(post_save, sender=UserProfile)
def post_save_user(sender, **kwargs):
user = kwargs.get('instance')
if kwargs.get('created'):
...
pre_save信号の挿入または更新であるかどうかを調べる方法
pre_save
を利用することで、データベース上のsave
アクションが既存のオブジェクトの更新や新しいオブジェクトの作成に関するものかどうかを判断できます。
これを達成するためには、モデルオブジェクトの状態をチェックすることができます:
@receiver(pre_save, sender=User)
def pre_save_user(sender, instance, **kwargs):
if not instance._state.adding:
print ('this is an update')
else:
print ('this is an insert')
save
動作が実行されるpre_save
に、 pre_save
信号が実行され、次のpre_save
出力されます。
-
this is an update
アクションから導出されたアクションの場合のthis is an update
です。 -
this is an insert
アクションが挿入アクションから派生した場合のthis is an insert
です。
このメソッドは、追加のデータベースクエリを必要としないことに注意してください。
拡張モデルへの信号継承
Djangoのシグナルは登録時に正確なクラス署名に制限されているため、サブクラス化されたモデルはすぐに同じシグナルに登録されません。
このモデルと信号を取る
class Event(models.Model):
user = models.ForeignKey(User)
class StatusChange(Event):
...
class Comment(Event):
...
def send_activity_notification(sender, instance: Event, raw: bool, **kwargs):
"""
Fire a notification upon saving an event
"""
if not raw:
msg_factory = MessageFactory(instance.id)
msg_factory.on_activity(str(instance))
post_save.connect(send_activity_notification, Event)
拡張モデルでは、信号を各サブクラスに手作業で添付して、影響を受けないようにする必要があります。
post_save.connect(send_activity_notification, StatusChange)
post_save.connect(send_activity_notification, Comment)
Python 3.6では、いくつかの追加のクラスメソッドを活用して、このバインディングを自動化するクラスを構築することができます。
class Event(models.Model):
@classmethod
def __init_subclass__(cls, **kwargs):
super().__init_subclass__(**kwargs)
post_save.connect(send_activity_notification, cls)