2010-10-26 8 views
12

मैं 100 या तो प्रविष्टियों के साथ एक मॉडल है - ग्राहक इन प्रविष्टियों को एक 'यादृच्छिक' के क्रम में प्रदर्शित करना चाहते हैं, लेकिन होता भी पेजिंग की तरह में वहाँ।Django में पेजिंग के साथ ऑब्जेक्ट्स के एक सेट पर "यादृच्छिक" ऑर्डर कैसे करें?

def my_view(request): 
    object_list = Object.objects.all().order_by('?') 
    paginator = Paginator(object_list, 10) 
    page = 1 # or whatever page we have 
    display_list = paginator.page(page) 
    .... 

तो मेरे सवाल का वास्तव में होना चाहिए - मैं कैसे हो सकता है मेरी object_list एक बार उपयोगकर्ता प्रति सत्र बनाया?

from random import shuffle 
object_list = list(object_list) 
shuffle(object_list) 
... continue with pagination ... 

टिप्पणी करते हैं, फिर भी है कि किसी सूची में कोई क्वेरीसमूह परिवर्तित इसका मूल्यांकन करेंगे:

उत्तर

10

वास्तव में कैसे यादृच्छिक इन होना चाहिए? यह प्रत्येक उपयोगकर्ता के लिए अलग होने की है, या यह महज अनियमितता की उपस्थिति कि महत्वपूर्ण है करता है?

यदि यह उत्तरार्द्ध है, तो आप बस एक क्षेत्र प्रश्न में मॉडल के लिए ordering कहा जाता है जोड़ने के लिए, और यादृच्छिक पूर्णांकों से पॉप्युलेट कर सकते हैं।

अन्यथा, जब तक कि रिकॉर्डसेट छोटा न हो (और, इसे दिया जा रहा है, मुझे संदेह है), फिर प्रत्येक सत्र के लिए एक अलग यादृच्छिक क्वेरीसेट संग्रहीत करना बहुत जल्दी हो सकता है जब तक कि आप नहीं जानते कि उपयोगकर्ता आधार बहुत है छोटे। यहाँ एक संभव समाधान है कि अनियमितता की नकल करता है लेकिन वास्तविकता में केवल 5 यादृच्छिक सेट बनाता है:

import random 
from django.core import cache 
RANDOM_EXPERIENCES=5 

def my_view(request): 
    if not request.session.get('random_exp'): 
     request.session['random_exp']=random.randrange(0,RANDOM_EXPERIENCES) 
    object_list = cache.get('random_exp_%d' % request.session['random_exp']) 
    if not object_list: 
     object_list = list(Object.objects.all().order_by('?')) 
     cache.set('random_exp_%d' % request.session['random_exp'], object_list, 100) 
    paginator = Paginator(object_list, 10) 
    page = 1 # or whatever page we have 
    display_list = paginator.page(page) 
    .... 

इस उदाहरण में, बजाय प्रत्येक उपयोगकर्ता (संभावित भंडारण में क्वेरीसमूहों के हजारों में जिसके परिणामस्वरूप) के लिए एक अलग क्वेरीसमूह बनाने और भंडारण की request.session (कैश की तुलना में एक कम कुशल भंडारण तंत्र है, जो बहुत ही कुशल वास्तव में, memcached की तरह कुछ का उपयोग करने के लिए सेट किया जा सकता है) में, हम अब सिर्फ 5 कैश में संग्रहित क्वेरीसमूहों, लेकिन उम्मीद है कि अधिकांश उपयोगकर्ताओं के लिए एक पर्याप्त यादृच्छिक अनुभव है। यदि आप अधिक यादृच्छिकता चाहते हैं, तो RANDOM_EXPERIENCES के मान को बढ़ाने में सहायता करनी चाहिए। मुझे लगता है कि आप शायद कुछ perfomance मुद्दों के साथ 100 के रूप में उच्च हो सकता है।

यदि रिकॉर्ड स्वयं बार-बार बदलते हैं, तो आप कैश के लिए अत्यधिक उच्च टाइमआउट सेट कर सकते हैं।

अद्यतन

यहाँ इसे लागू करने के एक तरीका है कि थोड़ा और अधिक स्मृति/भंडारण का उपयोग करता है, लेकिन यह सुनिश्चित करता है कि प्रत्येक उपयोगकर्ता अपने कैश समय बाहर के खतरे के बिना उनके क्वेरीसमूह करने के लिए "पर पकड़" कर सकते हैं (यह सोचते हैं कि 3 घंटे काफी लंबे समय है रिकॉर्ड देखने के लिए)।

import datetime 

... 

    if not request.session.get('random_exp'): 
     request.session['random_exp']="%d_%d" % ( 
      datetime.datetime.strftime(datetime.datetime.now(),'%Y%m%dH'), 
      random.randrange(0, RANDOM_EXPERIENCES) 
     ) 
    object_list = cache.get("random_exp_%s" % request.session['random_exp']) 
    if not object_list: 
     object_list = list(Object.objects.all().order_by('?')) 
     cache.set(cache_key, "random_exp_%s" % request.session['random_exp'], 60*60*4) 

यहां हम एक कैश किए गए क्वेरीसेट बनाते हैं जो 4 घंटे के लिए समय नहीं निकालता है। हालांकि, request.session कुंजी वर्ष, महीने, दिन और घंटे पर सेट की जाती है ताकि कोई उस घंटे के लिए रिकॉर्डसेट चालू देख सके। कोई भी जो पहले ही क्वेरीसेट देख चुका है, उसे कम से कम 3 घंटे (या जब तक उनका सत्र अभी भी सक्रिय है) के लिए इसे समाप्त होने से पहले देख पाएगा। अधिकतर, कैश में संग्रहीत 5 * RANDOM_EXPERIENCES क्वेरीसेट होंगे।

+0

अच्छा एक - केवल कैश करने के लिए दृश्य - कि पहले की तरह कैश इस्तेमाल नहीं किया। समझ में आता है। और आप सही हैं - यादृच्छिकता केवल उपस्थिति के लिए है, वास्तव में यादृच्छिक नहीं है। धन्यवाद। –

0

कार्रवाई का सर्वोत्तम कोर्स शायद एक सूची में अपना क्वेरीसमूह कन्वर्ट करने के लिए, और फिर इसे शफ़ल है। यदि आपकी ऑब्जेक्ट तालिका बड़ी हो जाती है तो यह एक प्रदर्शन दुःस्वप्न बन जाएगा।

आप उन वस्तुओं संग्रहीत करना चाहते हैं, तो आप वस्तु आईडी की एक सूची के साथ एक और मेज और सहयोगी उपयोगकर्ता आईडी बनाने के लिए, या एक सत्र कुकी में 100 आईडी या तो की दुकान या तो कर सकते हैं। और भी बहुत कुछ आप इस बारे में क्या कर सकते हैं नहीं है: HTTP राज्यविहीन, दृढ़ता कुकीज़ या एक डेटा स्टोर (एक RDBS प्रणाली अधिक होने की संभावना) का उपयोग करके प्राप्त किया जा सकता है।

1

डिफ़ॉल्ट Django मेटा विकल्प order_by का उपयोग करने का प्रयास करें?

एक प्रश्न चिह्न "?" यादृच्छिक आदेश में परिणाम

https://docs.djangoproject.com/en/1.3/ref/models/options/#ordering

+1

इस दृष्टिकोण के बारे में बात यह है कि (कम से कम पेजिनेशन के साथ) यादृच्छिकता अन्य पृष्ठों पर क्या नहीं रखती है। तो मैंने पहले पृष्ठ पर जो कुछ देखा वह अभी भी अन्य पृष्ठों पर दिखाई दे सकता है। – wasabigeek

0

@Jordan रेइटर समाधान वास्तव में महान। लेकिन इसका उपयोग करते समय एक छोटी सी समस्या है। यदि रिकॉर्ड अपडेट किया गया है, तो इसे प्रभावी होने में एक लंबा समय लगेगा। इसके अलावा, अगर रिकॉर्ड की गणना बड़ी है तो यह बहुत अधिक कैश स्पेस का उपयोग करती है।

मैं इसे प्राथमिक कुंजी कॉलम केवल कैश करके अनुकूलित करता हूं। जब रिकॉर्ड अपडेट होते हैं, तो यह तुरंत प्रभावित होगा।

import random 
from django.core import cache 
from django.core.paginator import Paginator 
RANDOM_EXPERIENCES=5 

if not request.session.get('random_exp'): 
    request.session['random_exp']=random.randrange(0,RANDOM_EXPERIENCES) 
id_list = cache.get('random_exp_%d' % request.session['random_exp']) 
if not id_list: 
    id_list = [object['id'] for object in Object.objects.values('id').all().order_by('?')] 
    cache.set('random_exp_%d' % request.session['random_exp'], id_list, 60*60*4) 
paginator = Paginator(id_list, 9) 
page = 1 # or whatever page we have 
display_id_list = paginator.page(page) 
object_list = Object.objects.filter(id__in=display_id_list) 
संबंधित मुद्दे