Sök…


parametrar

Klass / Metod Varför
UserProfile () klass Klassen UserProfile utökar Djangos standardanvändarmodell .
metoden create_profile () Metoden create_profile () körs, när en Django- post_save signal släpps .

Anmärkningar

Nu, detaljerna.

Django-signaler är ett sätt att informera din app om vissa uppgifter (till exempel en modell före eller efter att spara eller radera) när den sker.

Med dessa signaler kan du utföra åtgärder efter eget val omedelbart att signalen släpps.

Till exempel, närhelst en ny Django-användare skapas släpper användarmodellen en signal med associerade param som t.ex. sender=User så att du specifikt kan rikta ditt lyssnande på signaler till en specifik aktivitet som händer, i detta fall en ny användarskapning .

I exemplet ovan är avsikten att skapa ett UserProfile-objekt direkt efter att ett User-objekt har skapats. Därför genom att lyssna på en post_save signal från User (standard Django Användar Model) specifikt skapar vi en UserProfile objekt strax efter en ny User skapas.

Django-dokumentationen ger omfattande dokumentation om alla tillgängliga signaler .

Exemplet ovan är dock att i praktiska termer förklara att ett typiskt användningsfall när signaler kan användas kan vara ett användbart tillägg.

"Med stor kraft, kommer stort ansvar". Det kan vara frestande att ha signaler spridda över hela appen eller projektet bara för att de är fantastiska. Tja, inte. Eftersom de är coola, gör dem inte till lösningen för alla enkla situationer som tänker på.

Signalerna är bra för, som vanligt, inte allt. Inloggning / Loggar, signalerna är bra. Viktiga modeller som släpper tecken, som användarmodellen, om det är bra.

Att skapa signaler för varje modell i din app kan bli överväldigande vid ett tillfälle och besegra hela idén om sparringsanvändningen av Django Signals.

Använd inte signaler när (baserat på boken Two Scoops of Django ):

  • Signalen hänför sig till en viss modell och kan flyttas in i en av modellens metoder, eventuellt kallas med save() .
  • Signalen kan ersättas med en anpassad modellhanteringsmetod.
  • Signalen hänför sig till en viss vy och kan flyttas in i den vyn

Det kan vara okej att använda signaler när:

  • Din signalmottagare måste göra ändringar i mer än en modell.
  • Du vill skicka samma signal från flera appar och låta dem hanteras på samma sätt av en gemensam mottagare.
  • Du vill inaktivera en cache efter att en modell har sparats.
  • Du har ett ovanligt scenario som behöver återuppringning, och det finns inget annat sätt att hantera det förutom att använda en signal. Till exempel vill du utlösa något baserat på save() eller init() för en tredje parts app-modell. Du kan inte ändra tredjepartskoden och det kan vara omöjligt att utöka den, så en signal ger en trigger för ett återuppringning.

Utöka exempel på användarprofil

Det här exemplet är ett fragment som tas från den utvidgade Django-användarprofilen som en Pro

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)

Olika syntax för att posta / pre en signal

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

Hur man hittar om det är en insats eller uppdatering i pre_save signalen

Genom att använda pre_save vi avgöra om en save vår databas handlade om att uppdatera ett befintligt objekt eller skapa ett nytt.

För att uppnå detta kan du kontrollera modellobjektets tillstånd:

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

Nu varje gång en save åtgärd äger rum, kommer pre_save signalen att köras och skrivs ut:

  • this is an update om åtgärden härrör från en uppdateringsåtgärd.
  • this is an insert om åtgärden härrör från en insert-handling.

Observera att den här metoden inte kräver några ytterligare databasfrågor.

Ärver signaler på utökade modeller

Djangos signaler är begränsade till exakta klassunderskrifter vid registrering, och därför klassificeras underklassade modeller inte omedelbart på samma signal.

Ta till exempel den här modellen och signalera

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)

Med utökade modeller måste du ansluta signalen manuellt till varje underklass annars kommer de inte att utföras.

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

Med Python 3.6 kan du utnyttja några ytterligare klassmetoder som byggs in i klasser för att automatisera denna bindning.

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
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow