サーチ…


パラメーター

クラス/メソッドなぜ
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)


Modified text is an extract of the original Stack Overflow Documentation
ライセンスを受けた CC BY-SA 3.0
所属していない Stack Overflow