Suche…


Parameter

Klasse / Methode Das Warum
UserProfile () Klasse Die UserProfile-Klasse erweitert das Standardbenutzermodell von Django .
Methode create_profile () Die create_profile () -Methode wird ausgeführt, wenn ein post_save Signal eines Django-Benutzermodells freigegeben wird .

Bemerkungen

Nun zu den Details.

Mit Django-Signalen können Sie Ihre App über bestimmte Aufgaben informieren (z. B. vor oder nach dem Speichern oder Löschen eines Modells), wenn sie ausgeführt werden.

Mit diesen Signalen können Sie Aktionen Ihrer Wahl ausführen, sobald das Signal ausgelöst wird.

Jedes Mal , wenn ein neuer Django-Benutzer erstellt wird, gibt das Benutzermodell ein Signal aus, wobei Parameter wie sender=User sodass Sie das Abhören von Signalen gezielt auf eine bestimmte Aktivität ausrichten können, die in diesem Fall eine neue Benutzererstellung ist .

Im obigen Beispiel soll ein UserProfile-Objekt erstellt werden, unmittelbar nachdem ein User-Objekt erstellt wurde. post_save wir speziell auf ein post_save Signal des User (das standardmäßige Django-Benutzermodell) hören, erstellen wir ein UserProfile Objekt, unmittelbar nachdem ein neuer User erstellt wurde.

Die Django-Dokumentation bietet eine umfassende Dokumentation aller verfügbaren Signale .

Das obige Beispiel soll jedoch in praktischer Hinsicht erklären, dass ein typischer Anwendungsfall bei der Verwendung von Signalen eine nützliche Ergänzung sein kann.

"Mit großer Macht kommt große Verantwortung". Es kann verlockend sein, Signale über Ihre gesamte App oder Ihr Projekt zu verteilen, nur weil sie großartig sind. Gut nicht. Weil sie cool sind, sind sie nicht die Lösung für jede einfache Situation, die Ihnen in den Sinn kommt.

Die Signale sind wie üblich großartig für alles. Anmelden / Abmelden, Signale sind großartig. Schlüsselmodelle, die Zeichen wie das Benutzermodell freigeben, sofern in Ordnung.

Das Erstellen von Signalen für jedes einzelne Modell in Ihrer App kann an einem bestimmten Punkt überwältigend werden und die ganze Idee der Sparring-Verwendung von Django-Signalen zunichte machen.

Verwenden Sie keine Signale, wenn (basierend auf dem Two Scoops of Django-Buch ):

  • Das Signal bezieht sich auf ein bestimmtes Modell und kann in eine der Methoden dieses Modells verschoben werden, die möglicherweise von save() aufgerufen werden.
  • Das Signal kann durch eine benutzerdefinierte Modellmanager-Methode ersetzt werden.
  • Das Signal bezieht sich auf eine bestimmte Ansicht und kann in diese Ansicht verschoben werden

Es kann in Ordnung sein, Signale zu verwenden, wenn:

  • Ihr Signalempfänger muss Änderungen an mehreren Modellen vornehmen.
  • Sie möchten dasselbe Signal von mehreren Apps ausgeben und von einem gemeinsamen Empfänger auf dieselbe Weise behandeln lassen.
  • Sie möchten einen Cache nach dem Speichern eines Modells ungültig machen.
  • Sie haben ein ungewöhnliches Szenario, für das ein Rückruf erforderlich ist, und es gibt keine andere Möglichkeit, als nur ein Signal zu verwenden. Sie möchten beispielsweise etwas auslösen, das auf dem save() oder dem init() des Modells einer Drittanbieter-App basiert. Sie können den Code des Drittanbieters nicht ändern. Das Erweitern des Codes ist möglicherweise nicht möglich. Daher gibt ein Signal einen Auslöser für einen Rückruf aus.

Beispiel für ein Benutzerprofil erweitern

Dieses Beispiel ist ein Ausschnitt aus dem Extending Django User Profile wie ein Profi

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)

Andere Syntax, um ein Signal zu posten / vorzugeben

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'):
        ...

So finden Sie heraus, ob es sich um ein Insert oder ein Update im pre_save-Signal handelt

Mit pre_save wir feststellen, ob es sich bei einer save in unserer Datenbank darum handelt, ein vorhandenes Objekt zu aktualisieren oder ein neues zu erstellen.

Um dies zu erreichen, können Sie den Zustand des Modellobjekts überprüfen:

    @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')

Jedes Mal, wenn eine save wird, wird das Signal pre_save ausgeführt und gedruckt:

  • this is an update wenn die Aktion von einer Aktualisierungsaktion abgeleitet wurde.
  • this is an insert wenn die Aktion von einer Einfügeaktion abgeleitet wurde.

Beachten Sie, dass diese Methode keine zusätzlichen Datenbankabfragen erfordert.

Vererbung von Signalen bei erweiterten Modellen

Die Signale von Django sind bei der Registrierung auf genaue Klassensignaturen beschränkt, so dass Unterklassenmodelle nicht sofort auf demselben Signal registriert werden.

Nehmen Sie dieses Modell und signalisieren Sie es zum Beispiel

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)

Bei erweiterten Modellen müssen Sie das Signal manuell an jede Unterklasse anhängen, andernfalls werden sie nicht beeinflusst.

post_save.connect(send_activity_notification, StatusChange)
post_save.connect(send_activity_notification, Comment)

Mit Python 3.6 können Sie einige zusätzliche Klassenmethoden für Klassen nutzen, um diese Bindung zu automatisieren.

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
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow