# Django 5.2.8 documentation

# Signaler

Django innehåller en ”signal dispatcher” som hjälper frikopplade applikationer att få meddelanden när åtgärder inträffar någon annanstans i ramverket. I ett nötskal tillåter signaler vissa avsändare att meddela en uppsättning mottagare att någon åtgärd har ägt rum. De är särskilt användbara när många kodstycken kan vara intresserade av samma händelser.

En tredjepartsapp kan t.ex. registrera sig för att få meddelanden om ändringar i inställningarna:

    from django.apps import AppConfig
    from django.core.signals import setting_changed

    def my_callback(sender, **kwargs):
        print("Setting changed!")

    class MyAppConfig(AppConfig):
        ...

        def ready(self):
            setting_changed.connect(my_callback)

Djangos inbyggda signaler låter användarkoden få meddelande om vissa åtgärder.

Du kan också definiera och skicka dina egna anpassade signaler. Se definiera-och-sända-signaler nedan.

Varning

Signaler ger sken av lös koppling, men de kan snabbt leda till kod som är svår att förstå, justera och felsöka.

Om möjligt bör du välja att anropa hanteringskoden direkt i stället för att skicka den via en signal.

## Lyssna på signaler

För att ta emot en signal registrerar du en mottagarfunktion med metoden `Signal.connect()`. Mottagarfunktionen anropas när signalen skickas. Alla signalens mottagarfunktioner anropas en i taget, i den ordning de registrerades.

Signal.connect(receiver, sender=None, weak=True, dispatch_uid=None)
  Parametrar:

    - receiver – Den callback-funktion som kommer att anslutas till denna signal. Se Mottagarens funktioner för mer information.

    - sender – Anger en viss avsändare att ta emot signaler från. Se Anslutning till signaler som skickas av specifika avsändare för mer information.

    - weak – Django lagrar signalhanterare som svaga referenser som standard. Således, om din mottagare är en lokal funktion, kan den vara garbage collected. För att förhindra detta, skicka `weak=False` när du anropar signalens `connect()` metod.

    - dispatch_uid – En unik identifierare för en signalmottagare i de fall där dubbla signaler kan skickas. Se Förhindra dubblerade signaler för mer information.

Låt oss se hur detta fungerar genom att registrera en signal som anropas efter varje HTTP-begäran är klar. Vi kommer att ansluta till `request_finished`-signalen.

### Mottagarens funktioner

Först måste vi definiera en mottagarfunktion. En mottagare kan vara vilken Python-funktion eller metod som helst:

    def my_callback(sender, **kwargs):
        print("Request finished!")

Observera att funktionen tar ett `avsändare`-argument, tillsammans med jokertecken för nyckelordsargument (`**kwargs`); alla signalhanterare måste ta dessa argument.

Vi kommer att titta på sändare lite senare, men just nu tittar vi på `**kwargs` argumentet. Alla signaler skickar nyckelordsargument, och kan ändra dessa nyckelordsargument när som helst. När det gäller `request_finished` är det dokumenterat att den inte skickar några argument, vilket innebär att vi kan frestas att skriva vår signalhantering som `my_callback(sender)`.

Detta skulle vara fel - i själva verket kommer Django att kasta ett fel om du gör det. Det beror på att argument när som helst kan läggas till i signalen och din mottagare måste kunna hantera dessa nya argument.

Mottagare kan också vara asynkrona funktioner, med samma signatur men deklarerade med `async def`:

    async def my_callback(sender, **kwargs):
        await asyncio.sleep(5)
        print("Request finished!")

Signaler kan skickas antingen synkront eller asynkront och mottagarna kommer automatiskt att anpassas till rätt anropsstil. Se Skicka signaler för mer information.

### Ansluta mottagarfunktioner

Det finns två sätt att ansluta en mottagare till en signal. Du kan välja den manuella anslutningsvägen:

    from django.core.signals import request_finished

    request_finished.connect(my_callback)

Alternativt kan du använda en `receiver()`-dekorator:

receiver(signal, **kwargs)
  Parametrar:

    - signal – En signal eller en lista med signaler att ansluta en funktion till.

    - kwargs – Argument med nyckelord med jokertecken att skicka till en funktion.

Så här kommer du i kontakt med inredaren:

    from django.core.signals import request_finished
    from django.dispatch import receiver

    @receiver(request_finished)
    def my_callback(sender, **kwargs):
        print("Request finished!")

Nu kommer vår funktion `my_callback` att anropas varje gång en begäran avslutas.

Var ska den här koden finnas?

I strikt mening kan signalhanterings- och registreringskoden placeras var som helst, även om det rekommenderas att undvika applikationens rotmodul och dess `models`-modul för att minimera bieffekterna av importerad kod.

I praktiken definieras signalhanterare vanligtvis i en `signals` undermodul i den applikation de relaterar till. Signalmottagare ansluts i metoden `ready()` i din applikation configuration class. Om du använder `receiver()`-dekoratorn, importera submodulen `signals` i `ready()`, detta kommer implicit att ansluta signalhanterare:

    from django.apps import AppConfig
    from django.core.signals import request_finished

    class MyAppConfig(AppConfig):
        ...

        def ready(self):
            # Implicitly connect signal handlers decorated with @receiver.
            from . import signals

            # Explicitly connect a signal handler.
            request_finished.connect(signals.my_callback)

Observera

Metoden `ready()` kan köras mer än en gång under testning, så du kanske vill skydda dina signaler från duplicering, särskilt om du planerar att skicka dem inom tester.

### Anslutning till signaler som skickas av specifika avsändare

Vissa signaler skickas många gånger, men du kommer bara att vara intresserad av att ta emot en viss delmängd av dessa signaler. Tänk till exempel på `django.db.models.signals.pre_save`-signalen som skickas innan en modell sparas. För det mesta behöver du inte veta när någon modell sparas - bara när en specifik modell sparas.

I dessa fall kan du registrera dig för att ta emot signaler som endast skickas av vissa avsändare. I fallet med `django.db.models.signals.pre_save` kommer avsändaren att vara den modellklass som sparas, så du kan ange att du bara vill ha signaler som skickas av vissa modeller:

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

    @receiver(pre_save, sender=MyModel)
    def my_handler(sender, **kwargs): ...

Funktionen `my_handler` anropas endast när en instans av `MyModel` sparas.

Olika signaler använder olika objekt som sina avsändare; du måste konsultera inbyggd signaldokumentation för detaljer om varje enskild signal.

### Förhindra dubblerade signaler

Under vissa omständigheter kan koden som kopplar mottagare till signaler köras flera gånger. Detta kan leda till att din mottagarfunktion registreras mer än en gång och därmed anropas lika många gånger för en signalhändelse. Till exempel kan metoden `ready()` köras mer än en gång under testning. Mer generellt inträffar detta överallt där ditt projekt importerar modulen där du definierar signalerna, eftersom signalregistreringen körs så många gånger som den importeras.

Om detta beteende är problematiskt (t.ex. när du använder signaler för att skicka ett e-postmeddelande när en modell sparas) ska du ange en unik identifierare som argumentet `dispatch_uid` för att identifiera din mottagarfunktion. Denna identifierare är vanligtvis en sträng, men det räcker med vilket hashbart objekt som helst. Slutresultatet är att din mottagarfunktion bara kommer att vara bunden till signalen en gång för varje unikt `dispatch_uid`-värde:

    from django.core.signals import request_finished

    request_finished.connect(my_callback, dispatch_uid="my_unique_identifier")

## Definiera och skicka signaler

Dina applikationer kan dra nytta av signalinfrastrukturen och tillhandahålla sina egna signaler.

När ska man använda anpassade signaler

Signaler är implicita funktionsanrop som gör felsökningen svårare. Om sändaren och mottagaren av din anpassade signal båda finns inom ditt projekt är det bättre att använda ett explicit funktionsanrop.

### Definiera signaler

class Signal

Alla signaler är `django.dispatch.Signal`-instanser.

Till exempel:

    import django.dispatch

    pizza_done = django.dispatch.Signal()

Detta deklarerar en `pizza_done` signal.

### Sänder signaler

Det finns två sätt att skicka signaler synkront i Django.

Signal.send(sender, **kwargs)

Signal.send_robust(sender, **kwargs)

Signaler kan också skickas asynkront.

Signal.asend(sender, **kwargs)

Signal.asend_robust(sender, **kwargs)

För att skicka en signal anropar du antingen `Signal.send()`, `Signal.send_robust()`, `await Signal.asend()` eller `await Signal.asend_robust()`. Du måste ange argumentet `sender` (som oftast är en klass) och kan ange så många andra nyckelordsargument som du vill.

Så här kan det till exempel se ut när vi skickar vår signal `pizza_done`:

    class PizzaStore:
        ...

        def send_pizza(self, toppings, size):
            pizza_done.send(sender=self.__class__, toppings=toppings, size=size)
            ...

Alla fyra metoderna returnerar en lista med tupelpar `[(receiver, response), ...]`, som representerar listan över anropade mottagarfunktioner och deras svarsvärden.

`send()` skiljer sig från `send_robust()` i hur undantag som skapas av mottagarfunktioner hanteras. `send()` fångar inte upp några undantag som tas upp av mottagare; den tillåter helt enkelt att fel sprids. Därför kan det hända att inte alla mottagare får meddelande om en signal när det uppstår ett fel.

`send_robust()` fångar upp alla fel som härrör från Pythons klass `Exception` och ser till att alla mottagare meddelas om signalen. Om ett fel inträffar returneras felinstansen i tuple-paret för den mottagare som orsakade felet.

Spårningarna finns i attributet `__traceback__` i de fel som returneras när man anropar `end_robust()`.

`asend()` liknar `send()`, men det är en coroutine som måste inväntas:

    async def asend_pizza(self, toppings, size):
        await pizza_done.asend(sender=self.__class__, toppings=toppings, size=size)
        ...

Oavsett om mottagarna är synkrona eller asynkrona kommer de att anpassas korrekt till om `send()` eller `asend()` används. Synkrona mottagare kommer att anropas med `sync_to_async()` när de anropas via `asend()`. Asynkrona mottagare kommer att anropas med `async_to_sync()` när de anropas via `send()`. I likhet med fallet för middleware, finns det en liten prestandakostnad för att anpassa mottagare på detta sätt. Observera att för att minska antalet byten av sync/async-anropsstil inom ett `send()`- eller `asend()`-anrop, grupperas mottagarna efter om de är asynkrona eller inte innan de anropas. Detta innebär att en asynkron mottagare som registreras före en synkron mottagare kan exekveras efter den synkrona mottagaren. Dessutom exekveras asynkrona mottagare samtidigt med hjälp av `asyncio.gather()`.

Alla inbyggda signaler, utom de som ingår i den asynkrona request-response-cykeln, skickas med `Signal.send()`.

## Bortkoppling av signaler

Signal.disconnect(receiver=None, sender=None, dispatch_uid=None)

För att koppla bort en mottagare från en signal, anropa `Signal.disconnect()`. Argumenten är de som beskrivs i `Signal.connect()`. Metoden returnerar `True` om en mottagare har kopplats bort och `False` om så inte är fallet. När `sender` skickas som en latent referens till `<app label>.<model>`, returnerar denna metod alltid `None`.

Argumentet `receiver` anger den registrerade mottagare som ska kopplas bort. Det kan vara `None` om `dispatch_uid` används för att identifiera mottagaren.