मुझे जो भी करने की कोशिश कर रहे हैं, उसे करने के लिए मुझे कोई शानदार तरीका नहीं दिख रहा है। यदि आप थोड़ा डी-सामान्यीकरण स्वीकार करने के इच्छुक हैं, तो मैं संदेशों को चिह्नित करने के लिए पूर्व-सहेजने वाले सिग्नल की सिफारिश करता हूं।
#In your model
head = models.BooleanField(default=True)
#As a signal plugin:
def check_head(sender, **kwargs):
message = kwargs['instance']
if hasattr(message,'no_check_head') and message.no_check_head:
return
previous_message = Message.objects.filter(time__lt=message.time).order_by('-time')[0]
if message.source == previous_message.source:
message.head = False
next_message = Message.objects.filter(time__gt=message.time).order_by('time')[0]
if message.source == next_message.source:
next_message.head = False
next_message.no_check_head
next_message.save()
तो आपकी क्वेरी जादुई सरल हो जाता है:
messages = Message.objects.filter(head=True).order_by('time')[0:15]
काफी ईमानदारी से कहूं तो ... संकेत श्रोता एक मैंने लिखा से थोड़ा अधिक जटिल हो करना होगा। मेरे दृष्टिकोण में अंतर्निहित खोए गए सिंक्रनाइज़ेशन/खोए गए अपडेट की समस्याएं हैं, जिनके समाधान आपके सर्वर के आधार पर अलग-अलग होंगे (यदि यह एकल-संसाधित, बहु-थ्रेडेड है, तो एक पायथन Lock
ऑब्जेक्ट आपको प्राप्त करना चाहिए, लेकिन यदि यह बहु-संसाधित है, तो आपको फ़ाइलों या डेटाबेस ऑब्जेक्ट्स के आधार पर लॉकिंग को लागू करने की आवश्यकता होगी)। साथ ही, आपको निश्चित रूप से एक संबंधित डिलीट सिग्नल श्रोता लिखना होगा।
स्पष्ट रूप से इस समाधान में कुछ डेटाबेस हिट जोड़ना शामिल है, लेकिन वे दृश्य के विपरीत संपादन पर हैं, जो आपके लिए उपयोगी हो सकता है। अन्यथा, शायद एक क्रूडर दृष्टिकोण पर विचार करें: 30 कहानियों को पकड़ें, दृश्य में लूप करें, उन लोगों को नकार दें जिन्हें आप प्रदर्शित नहीं करेंगे, और यदि आपके पास 15 शेष हैं, तो उन्हें प्रदर्शित करें, अन्यथा दोहराएं। निश्चित रूप से एक भयानक सबसे खराब स्थिति परिदृश्य, लेकिन शायद भयानक औसत मामला नहीं?
यदि आपके पास एक सर्वर कॉन्फ़िगरेशन है जो एक एकल प्रक्रिया का उपयोग करता है जो बहु-थ्रेडेड है, तो लॉक या आरएलॉक को चाल चलनी चाहिए।फिर
import thread
lock = thread.allocate_lock()
def check_head(sender, **kwargs):
# This check must come outside the safe zone
# Otherwise, your code will screech to a hault
message = kwargs['instance']
if hasattr(message,'no_check_head') and message.no_check_head:
return
# define safe zone
lock.acquire()
# see code above
....
lock.release()
, एक इसी हटाने के संकेत के रूप में अच्छी तरह से महत्वपूर्ण है: यहाँ गैर रैत्रांत ताला के साथ एक संभव कार्यान्वयन है।
संपादित करें: कई या अधिक सर्वर कॉन्फ़िगरेशन (जैसे अपाचे) prefork होगा, जिसका अर्थ है कि कई प्रक्रियाएं चल रही हैं। उपरोक्त कोड उस मामले में बेकार होगा। फोर्क प्रक्रियाओं के साथ सिंक्रनाइज़ करना प्रारंभ करने के तरीकों के लिए this page देखें।
मुझे लगता है कि यह सामान्य दृष्टिकोण है जिसे आप लेना चाहते हैं, हालांकि आप memcached में last_source को संग्रहीत करके डेटाबेस हिट को प्रतिस्थापित कर सकते हैं; भारी समेकन के तहत अभी भी एक संभावित दौड़ की स्थिति होगी, लेकिन अगर इसे 100% सही नहीं होना चाहिए ... –
जैसा कि आपने कहा, सही विकल्प नहीं है, लेकिन मुझे अभी भी लगता है कि सबसे अच्छा है। धन्यवाद – Michael
इसके अलावा ... मुझे लगता है कि मुझे हमेशा संकेतों का उपयोग करना पसंद आया है ... लेकिन सहेजने की विधि को ओवरराइड करना वही काम कर सकता है। कुछ स्टाइलिस्ट शुद्धवादियों का तर्क है कि यह "सही चीज़" है। –