Wszystko, mam problem z sygnałami Django.

Mam model W celu przyspieszenia reakcji ładunków stron, rozładowuję intensywne przetwarzanie, które należy wykonać, poprzez połączenie do drugiego lokalnego serwera WebServer, które używamy, zarówno przy użyciu tej samej bazy danych. Widzę zachowanie, w którym proces wywołujący może pobrać obiekt, ale zwany proces nie może. Zarówno port 80, jak i port [Port] wskazują na procesy Django uciekające z tej samej bazy danych.

. W modelach.py.

class A(models.Model):
    stuff...

def trigger_on_post_save( sender, instance, create, raw, **keywords):
    #This line works
    A.objects.get( pk=instance.pk )
    #then we call this
    urlopen( r'http://127.0.0.1:[port]' + 
        reverse(some_view_url, args(instance_pk) ).read()

post_save.connect( trigger_on_post_save, A )

W views.py

def some_view_function( request, a_pk ):
    #This line raises an object_not_found exception
    A.objects.get( pk=a_pk )

Ponadto po wywołaniu Urlopen podnosi wyjątek, obiekt nie istnieje w bazie danych. To było moje zrozumienie, że po_save został wywołany po zapisaniu obiektu i zapisywania do bazy danych. Czy to jest nieprawidłowe?

15
mklauber 16 grudzień 2011, 03:59

3 odpowiedzi

Wprowadziliśmy w podobny problem i skończyliśmy za pomocą On_Commit Callback ( Uwaga : Jest to możliwe tylko z Django & GT; = 1,9). Więc możesz zrobić coś w rodzaju:

from django.db import transaction

class A(models.Model):
    stuff...

def trigger_on_post_save( sender, instance, create, raw, **keywords):
    def on_commit():
        urlopen(r'http://127.0.0.1:[port]' + 
                 reverse(some_view_url, args(instance_pk) ).read()
    transaction.on_commit(on_commit)

post_save.connect( trigger_on_post_save, A )

Oto pomysł, że zadzwonisz do twojego punktu końcowego po transakcja została popełniona, instancja zaangażowana w transakcję zostanie już zapisana;).

15
Yoanis Gil 13 maj 2016, 15:53

Miło jest używać dekoratorów. Jest nieco rozszerzona wersja odpowiedzi Yoanis-Gil:

from django.db import transaction
from django.db.models.signals import post_save

def on_transaction_commit(func):
    def inner(*args, **kwargs):
        transaction.on_commit(lambda: func(*args, **kwargs))
    return inner


@receiver(post_save, sender=A)
@on_transaction_commit
def trigger_on_post_save(sender, **kwargs):
    # Do things here
4
raratiru 21 styczeń 2020, 17:05

Miał ten sam problem podczas tworzenia nowego modelu z admin Django. Nadrzędna metoda ModelAdmin.save_model do zarządzania transakcją ręcznie pracującą.

def save_model(self, request, obj, form, change):
    from django.db import transaction
    with transaction.commit_on_success():
       super(ModelAdmin, self).save_model(request, obj, form, change)

    # write your code here
1
Venkat Kotra 28 grudzień 2015, 10:24