2011-12-15 3 views
13

सब, मुझे django सिग्नल के साथ कोई समस्या है।मैं अपने post_save सिग्नल के दौरान किसी ऑब्जेक्ट को क्यों एक्सेस कर सकता हूं, लेकिन जब मैं उस सिग्नल के भीतर कोड ट्रिगर नहीं करता जो इसे किसी अन्य प्रक्रिया पर कॉल करता है

मेरे पास एक मॉडल है पेज लोड की प्रतिक्रिया को तेज करने के प्रयास में, मैं कुछ गहन प्रसंस्करण को ऑफ़लोड कर रहा हूं, जो एक दूसरे डेटाबेसहोस्ट वेबसर्वर को कॉल के माध्यम से किया जा सकता है, दोनों एक ही डेटाबेस का उपयोग करते हुए । मैं व्यवहार देख रहा हूं जहां कॉलिंग प्रक्रिया ऑब्जेक्ट को पुनर्प्राप्त कर सकती है, लेकिन कहा जाता है कि प्रक्रिया नहीं हो सकती है। पोर्ट 80 और पोर्ट [पोर्ट] दोनों एक ही डेटाबेस से चल रहे django प्रक्रियाओं को इंगित कर रहे हैं।

views.py

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

में models.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) 

में इसके अलावा, के बाद urlopen कॉल एक अपवाद को जन्म देती है, वस्तु डेटाबेस में मौजूद नहीं है। यह मेरी समझ थी कि ऑब्जेक्ट को सहेजने के बाद post_save को कॉल किया गया था, और डेटाबेस में लिखा गया था। क्या यह गलत है?

+0

चाहिए ना हो: रिवर्स (some_view_url, आर्ग (instance.pk)) .read()? सेलेरी की ओर बढ़ने के लिए –

उत्तर

12

मुझे विश्वास है कि सहेजने के बाद पोस्ट_सेव आग लगती है, लेकिन लेनदेन से पहले डेटाबेस में आता है। डिफ़ॉल्ट रूप से, अनुरोध पूरा होने के बाद Django केवल डेटाबेस में परिवर्तन करता है। आपकी समस्या का

दो संभव समाधान:

  1. Manage your transactions manually, और एक कस्टम संकेत आग आप के लिए प्रतिबद्ध हैं।
  2. आपकी दूसरी प्रक्रिया के अनुरोध के लिए थोड़ी देर प्रतीक्षा करें।

हालांकि ईमानदार होने के लिए, आपका पूरा सेटअप थोड़ा बुरा लगता है। आपको असीमित कार्य कतार के लिए शायद Celery पर देखना चाहिए।

+0

+1। यह एसिंक कतार के लिए एक आदर्श उपयोग-मामला है। –

+0

tbh, मुझे एक सेलेरी/खरगोश एमक्यू सेटअप पर जाना अच्छा लगेगा, लेकिन पिछले डेवलपर ने पहले से ही अपना टास्क क्यूयू सिस्टम लागू किया था, इसलिए मैं बस इसे पिगबैक करने की कोशिश कर रहा था। लेनदेन के बारे में स्पष्टीकरण के लिए धन्यवाद, यह वही है जो मैं खोज रहा था। ** संपादित करें **: मैं इस तरह की कुछ स्वीकृति देने के लिए हमारी हिमनद सॉफ्टवेयर सत्यापन टीम को दबाए रखूंगा। – mklauber

+7

बस जोड़ना चाहते हैं कि अजवाइन का उपयोग इस मुद्दे को नहीं बदलेगा - मेरे पास एक सेलरी कार्य पुराने डेटा प्राप्त कर रहा है क्योंकि अनुरोध() अनुरोध का लेनदेन अभी तक नहीं किया गया है। आपको या तो अपने Task.run() या - बेहतर में देरी जोड़ने की आवश्यकता है - "post_save" के बजाय "post_commit" कार्य को तुरंत चालू करें। Django इस सिग्नल (अभी तक) प्रदान नहीं करता है लेकिन https://github.com/davehughes/django-transaction-signals –

1

django व्यवस्थापक से नया मॉडल बनाते समय एक ही समस्या थी। मैन्युअल रूप से काम करने के लिए ModelAdmin.save_model विधि ओवरराइडिंग।

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 
16

हम ने वही समस्या में पड़ गए और हम प्रयोग कर on_commit callback समाप्त हो गया (नोट: यह Django> = 1.9 के साथ संभव है)। तो, आप संभव तरह कुछ कर सकता है:

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) 

विचार यहाँ है कि आप अपने अंतिम बिंदु के बाद लेन-देन किया गया है बुला हो जायेंगे, तो उदाहरण के लेनदेन में शामिल पहले ही सुरक्षित हो जाएगा;)।

+1

+1: यह Django 1.9 के लिए साफ 'बैटरी शामिल' समाधान है। ध्यान दें कि आप इसे 'pre_save' सिग्नल से भी उपयोग कर सकते हैं, क्योंकि यह लेनदेन करने पर ही आग लग जाएगा, इसलिए उदा। आप डेटाबेस को हिट करने से पहले आवश्यक कुछ मॉडल विशेषताओं को बदल सकते हैं .. – TimStaley

+0

यदि आपको Django 1.6 - 1.8 का समर्थन करने की आवश्यकता है तो https://django-transaction-hooks.readthedocs.io/en/latest/ देखें सुविधा का स्रोत जो 1.9 में जोड़ा गया था –

0

सजावट करने वालों का उपयोग करने के लिए यह अच्छी जगह है। वहाँ थोड़ा बढ़ाया है @ yoanis-गिल के जवाब के संस्करण:

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 
संबंधित मुद्दे

 संबंधित मुद्दे