2017-12-16 23 views
5

एक django ऐप में मैं async कार्यों को चला रहा हूं और उपयोगकर्ता को प्रगति, त्रुटियां आदि दिखाना चाहता हूं। यदि त्रुटियां हैं, तो उपयोगकर्ता को उस पृष्ठ पर रीडायरेक्ट किया जाना चाहिए जहां समस्या को ठीक करने के लिए अतिरिक्त इनपुट या कुछ कार्रवाई की आवश्यकता हो। अजवाइन के काम से आगे के अंत तक संवाद करने का सबसे अच्छा तरीका क्या है?Django अजवाइन कार्यकर्ता वास्तविक समय की स्थिति और परिणाम संदेश भेजने के लिए

यहाँ छद्म कोड में एक बुनियादी संरचना है:

# views.py 
from tasks import run_task 

def view_task(): 
    run_task.delay() 
    return render(request, 'template.html') 

# tasks.py 
from compute_module import compute_fct 

@shared_task 
def run_task(): 
    result = compute_fct() 

    # how to catch status update messages from compute_module while compute_fct is running?? 

    if result == 'error': 
     handle_error() 
    else: 
     handle_succes()  

# compute_module 
import pandas as pd 

def compute_fct(): 
    # send message: status = loading file 
    df = pd.read_csv('test.csv') 
    # send message: status = computing 
    val = df['col'].mean() 

    if val is None: 
     return {'status':'error'} 
    else: 
     return {'status':'success','val':val} 

क्या मैं आदर्श रूप चाहेगा:

  • compute_module.py मॉड्यूल अजगर देशी लकड़हारा उपयोग करता है। कर्तव्यों को अलग करके मैं लॉगिंग को जितना संभव हो उतना सामान्य रखना चाहता हूं और मानक पायथन/डीजेंगो लॉगर्स का उपयोग करना चाहता हूं। लेकिन वे सामने के अंत में संदेश भेजने के लिए डिज़ाइन नहीं किए गए प्रतीत होते हैं।
  • अजवाइन काम किसी भी तरह लॉग संभालती है और इसके बजाय stdout पर उन्हें प्रदर्शित करने में उन्हें पुनर्निर्देश
  • सामने के अंत js शो pusher करने और संभालती संदेशों

वहाँ अजवाइन कार्यकर्ता और सामने के बीच संवाद स्थापित करने के मानक तरीके हो सकते हैं अंत में मुझे पता नहीं है। यह परिदृश्य अक्सर होता है और मुझे आश्चर्य है कि इसे कार्यान्वित करना बहुत मुश्किल है। एक तरह से rabbitmq संदेश कतार या aws sns इस के लिए डिजाइन किया जाना चाहिए। नीचे संसाधन हैं जिन्हें मैंने देखा लेकिन उनमें से कोई भी बहुत अच्छी तरह से काम नहीं करता है लेकिन शायद मैं उलझन में हूं।

प्रवेश: इस सर्वर साइड पर लॉग इन करने, उपयोगकर्ता

अजवाइन कैम को संदेश भेजने के बारे में अधिक नहीं हो रहा है लगता है कि व्यवस्थापक निगरानी कार्यों के बारे में नहीं, सीन नहीं उपयोगकर्ता के लिए डिंग संदेशों

पुशर मुझे पसंद है लेकिन मैं इसके साथ compute_module.py मशक्कत करनी पड़ती है नहीं करना चाहती। उदाहरण के लिए मैं compute_module.py के अंदर कोई भी pusher.com एकीकरण नहीं करना पसंद करूंगा। लगता है कि मैं एक पुशर उद्देश्य यह है कि पहले से ही ऐसा मॉड्यूल सिर्फ पुश संदेश कर सकते हैं instantiated कर दिया गया है पारित सकता है, लेकिन फिर मैं इसे पसंद करेंगे सामान्य होने के

+0

क्या आपके मामले में एक प्रगति रिपोर्ट स्थान होगा? आप एक कार्य चलाते हैं, यह किया जाता है या यह त्रुटियां होती है। यदि आप सबटास्क के रूप में विघटित एक कार्य चलाते हैं, तो क्या आप प्रत्येक उप के अंतिम आउटपुट को क्लाइंट को वापस धक्का देने के लिए वेबवर्कर का उपयोग कर सकते हैं? मैं भी वास्तव में * महसूस नहीं कर रहा हूं * उपयोगकर्ता प्रतिक्रिया तंत्र के रूप में पाइथन लॉगिंग - मुझे लगता है कि * अच्छा * आउटपुट प्राप्त करने पर संदेह है, एचटीएमएल के लिए esp इसके लायक होने से अधिक परेशानी होगी। –

उत्तर

0

एक ही रास्ता मैं रीयलटाइम की स्थिति प्राप्त करने में कामयाब रहा है बस कार्य में कुछ एसक्यूएल लिखने/एपीआई कॉल डालना है। कार्य के वापसी मूल्य के साथ चीजें करना बहुत आसान है क्योंकि आप केवल एक कस्टम कार्य वर्ग लिख सकते हैं।

मुझे पूरी तरह से यकीन नहीं है कि यह Django का उपयोग कैसे करता है लेकिन इसे ऐसा कुछ दिखना चाहिए।

class CustomTask(celery.Task): 
    def __call__(self, *args, **kwargs): 
     self.start_time = time.time() 

    def on_success(self, retval, task_id, args, kwargs): 
     do_success_stuff() 

    def on_failure(self, exc, task_id, args, kwargs, einfo): 
     do_failure_stuff() 

@shared_task(base=CustomTask) 
def do_stuff(): 
    return create_widgets() 

पूरी सूची यहां पाया जा सकता है: http://docs.celeryproject.org/en/latest/userguide/tasks.html#handlers

+0

ठीक है, यूआई पर पेज के बिना इन विजेट्स को कैसे दिखाया जाएगा? –

+0

मुझे यकीन है कि कहीं कहीं एक सुरुचिपूर्ण समाधान है लेकिन मैं अपने कार्यों को एक टेबल पर लिखता हूं और फिर स्थिति कॉलम अपडेट करता हूं। चूंकि आपके पास नौकरी बंद करने के तुरंत बाद task_id है, इसलिए आप नई स्थिति प्राप्त करने के लिए कुछ jquery जादू कर सकते हैं। शायद http://www.giantflyingsaucer.com/blog/?p=4310 जैसे कुछ – lpiner

0

तो नीचे ठीक है मैं इसे कैसे अब के लिए समाधान कर लिया है के लिए छद्म कोड है। असल में मैं https://pusher.com/docs/javascript_quick_start का उपयोग करता हूं और सर्वर-साइड तत्काल ऑब्जेक्ट को compute_module में पास करता है। एक नकारात्मक बात यह है कि पुशर संदेश अस्थिर हैं इसलिए मुझे LogPusher में उन्हें एक डीबी में स्टोर करने के लिए कुछ अतिरिक्त काम करने जा रहे हैं, किसी अन्य दिन के लिए कुछ ...

इसके अलावा मेरे वास्तविक कार्यान्वयन में मैं कार्य को ट्रिगर करता हूं एजेक्स कॉल के माध्यम से $(document).ready() में क्योंकि छोटे कार्यों को इतनी तेजी से पूरा किया गया कि उपयोगकर्ता कभी भी पुशर संदेश नहीं देख पाएगा क्योंकि कनेक्शन स्थापित नहीं किया गया था (उस ऐतिहासिक संदेश समस्या पर वापस)।

एक अन्य वैकल्पिक मार्ग जो मैं ऊपर उल्लेख नहीं किया था https://channels.readthedocs.io/en/latest/

# views.py 
from tasks import run_task 

def view_task(): 
    run_task.delay('event') 
    return render(request, 'template.html', 'pusher_event':'event') 


# tasks.py 
import pusher 
from django.conf import settings 
from compute_module import compute_fct 

class LogPusher(object): 
    def __init__(self, event): 
     self.pusher_client = pusher.Pusher(app_id=settings.PUSHER_APP_ID, 
         key=settings.PUSHER_KEY, 
         secret=settings.PUSHER_SECRET, 
         cluster=settings.PUSHER_CLUSTER, ssl=True) 
     self.event = event 

    def send(self, data): 
     self.pusher_client.trigger(settings.PUSHER_CHANNEL, self.event, json.dumps(data)) 

@shared_task 
def run_task(pusher_event): 

    log_pusher = LogPusher(pusher_event) 
    result = compute_fct(log_pusher) 

    # how to catch status update messages from compute_module while compute_fct is running?? 

    if result == 'error': 
      log_pusher.send('status':'error') 
    else: 
      log_pusher.send('status':'success') 


# compute_module.py 
import pandas as pd 

def compute_fct(log_pusher): 
    # send message: status = loading file 
    log_pusher.send('status':'loading file') 
    df = pd.read_csv('test.csv') 
    # send message: status = computing 
    log_pusher.send('status':'computing') 
    val = df['col'].mean() 

    if val is None: 
     return {'status':'error'} 
    else: 
     return {'status':'success','val':val} 


# context_processors.py 
# see https://stackoverflow.com/questions/433162/can-i-access-constants-in-settings-py-from-templates-in-django 
from django.conf import settings 

def pusher(request): 
    return {'PUSHER_KEY': settings.PUSHER_KEY, 'PUSHER_CLUSTER': settings.PUSHER_CLUSTER , 'PUSHER_CHANNEL': settings.PUSHER_CHANNEL } 


# template.html 
<script> 

var pusher = new Pusher("{{PUSHER_KEY}}", { 
    cluster: "{{PUSHER_CLUSTER}}", 
    encrypted: true  
}); 

var channel = pusher.subscribe("{{PUSHER_CHANNEL}}"); 
channel.bind("{{pusher_event}}", function(data) { 
    // process data 
}); 

</script> 
संबंधित मुद्दे