2009-03-12 12 views
5

में आइटम का समूह पर निर्भर करता है कि हम निम्न आवश्यकता है एक वेबसाइट Django/पायथन में लागू के लिए:पेजिंग Django

एक दृश्य पृष्ठ पर वेब पेजिंग प्रति 15 संदेशों से पता चला रहे हैं। जब एक ही स्रोत से दो या दो से अधिक संदेश होते हैं, जो दृश्य पर एक-दूसरे का अनुसरण करते हैं, तो उन्हें एक साथ समूहीकृत किया जाना चाहिए।

हो सकता है कि स्पष्ट नहीं है, लेकिन निम्नलिखित उदाहरण के साथ यह हो सकता है:

एक उदाहरण (इस बार एक पृष्ठ पर 5 संदेश के साथ) है:

Message1 Source1 
    Message2 Source2 
    Message3 Source2 
    Message4 Source1 
    Message5 Source3 
    ... 

इस रूप में दिखाया जाना चाहिए:

Message1 Source1 
Message2 Source2 (click here to 1 more message from Source2) 
Message4 Source1 
Message5 Source3 
Message6 Source2 

इसलिए प्रत्येक पृष्ठ पर पृष्ठ पर एक निश्चित संख्या में आइटम दिखाए जाते हैं, जहां कुछ को फिर से समूहित किया गया है।

हम सोच रहे हैं कि हम इस डेटा को इष्टतम और आसान तरीके से पूछने के लिए Django या MySQL क्वेरी कैसे बना सकते हैं। ध्यान दें कि पेजिंग का उपयोग किया जाता है और संदेशों को समय के अनुसार क्रमबद्ध किया जाता है।

पुनश्च: मुझे नहीं लगता कि वहाँ एसक्यूएल की प्रकृति के इस वजह के लिए एक सरल उपाय है, लेकिन कभी कभी जटिल समस्याओं को आसानी से किया जा सकता है

उत्तर

3

मुझे जो भी करने की कोशिश कर रहे हैं, उसे करने के लिए मुझे कोई शानदार तरीका नहीं दिख रहा है। यदि आप थोड़ा डी-सामान्यीकरण स्वीकार करने के इच्छुक हैं, तो मैं संदेशों को चिह्नित करने के लिए पूर्व-सहेजने वाले सिग्नल की सिफारिश करता हूं।

#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 देखें।

+0

मुझे लगता है कि यह सामान्य दृष्टिकोण है जिसे आप लेना चाहते हैं, हालांकि आप memcached में last_source को संग्रहीत करके डेटाबेस हिट को प्रतिस्थापित कर सकते हैं; भारी समेकन के तहत अभी भी एक संभावित दौड़ की स्थिति होगी, लेकिन अगर इसे 100% सही नहीं होना चाहिए ... –

+0

जैसा कि आपने कहा, सही विकल्प नहीं है, लेकिन मुझे अभी भी लगता है कि सबसे अच्छा है। धन्यवाद – Michael

+0

इसके अलावा ... मुझे लगता है कि मुझे हमेशा संकेतों का उपयोग करना पसंद आया है ... लेकिन सहेजने की विधि को ओवरराइड करना वही काम कर सकता है। कुछ स्टाइलिस्ट शुद्धवादियों का तर्क है कि यह "सही चीज़" है। –

1

मेरे पास है एक सरल, हालांकि सही नहीं, टेम्पलेट एकमात्र समाधान हल इसके लिए। टेम्पलेट में आप regroup टेम्पलेट टैग का उपयोग कर रिकॉर्ड्स को पुन: समूहित कर सकते हैं। पुनर्वर्गीकरण आप एक ही स्रोत से लगातार रिकॉर्ड छिपा कर सकते हैं के बाद: पृष्ठांकन:

{% regroup records by source as grouped_records %} 
{% for group in grouped_records %} 
    {% for item in group.list %} 
    <li{% if not forloop.first %} style="display:none"{% endif %}> 
     {{ item.message }} {{ iterm.source }} 
     {% if forloop.first %} 
     {% ifnotequal group.list|length 1 %} 
      <a href="#" onclick="...">Show more from the same source...</a> 
     {% endifnotequal %}   
     {% endif %} 
    </li> 
    {% endfor %} 
{% endfor %} 

यह अगर यह एक बात के लिए नहीं था अधिक उचित होगा। यदि आप प्रति पृष्ठ 15 आइटम प्रदर्शित करना चाहते हैं, और एक पृष्ठ पर पहले पांच स्रोत से हैं, अगले पांच से दूसरे हैं, और पिछले पांच अन्य हैं, तो पृष्ठ पर केवल तीन दृश्यमान आइटम होंगे।

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