2008-11-02 20 views
13

मेरे Django ऐप के लिए मेरे पास ईवेंट, रेटिंग और उपयोगकर्ता हैं। रेटिंग विदेशी कुंजी के माध्यम से घटनाओं और उपयोगकर्ताओं से संबंधित हैं। घटनाओं की एक सूची प्रदर्शित करते समय मैं उपयोगकर्ता_आईडी द्वारा ईवेंट की रेटिंग फ़िल्टर करना चाहता हूं, इसलिए मुझे पता है कि उपयोगकर्ता द्वारा कोई ईवेंट रेट किया गया है या नहीं।Django - संबंधित वस्तुओं पर फ़िल्टरिंग

अगर मैं कार्य करें:

event_list = Event.objects.filter(rating__user=request.user.id) 

... तो मैं सिर्फ घटनाओं है कि उपयोगकर्ता द्वारा दर्ज़ा दिया गया रहे हैं (request.user.id वर्तमान उपयोगकर्ता में लॉग इन के user_id देता है) और नहीं पूरे घटनाओं की सूची।

क्या मैं कस्टम एसक्यूएल के माध्यम से उत्पन्न किया जा सकता की जरूरत है:

SELECT * 
FROM `events_event` 
LEFT OUTER JOIN (
    SELECT * 
    FROM `events_rating` 
    WHERE user_id = ## 
) AS temp 
ON events_event.id = temp.user_id 

वहाँ एक आसान तरीका है तो मैं कस्टम एसक्यूएल उपयोग करने के लिए नहीं है?

उत्तर

15

filter विधि फ़िल्टरिंग के लिए है कि निर्दिष्ट मानदंडों के आधार पर कौन सी वस्तुएं लौटाई जाती हैं, इसलिए यह आप यहां नहीं चाहते हैं। एक विकल्प वर्तमान User के लिए दिए गए Event ऑब्जेक्ट्स के लिए सभी रेटिंग पुनर्प्राप्त करने के लिए दूसरी क्वेरी करना है।

मॉडल:

import collections 

from django.db import models 

class RatingManager(models.Manager): 
    def get_for_user(self, events, user): 
     ratings = self.filter(event__in=[event.id for event in events], 
           user=user) 
     rating_dict = collections.defaultdict(lambda: None) 
     for rating in ratings: 
      rating_dict[rating.event_id] = rating 
     return rating_dict 

class Rating(models.Model): 
    # ... 
    objects = RatingManager() 

दृश्य:

events = Event.objects.all() 
user_ratings = Rating.objects.get_for_user(events, request.user) 
context = { 
    'events': [(event, user_ratings[event.id]) for event in events], 
} 

टेम्पलेट:

{% for event, user_rating in events %} 
    {% if user_rating %} ... {% endif %} 
{% endfor %} 
1

Django का सबसे अच्छा उपयोग करने के लिए, आपको जुड़ने की कोशिश करने से बचने के लिए है।

ए "बाएं बाहरी शामिल" वास्तव में वैकल्पिक संबंधों वाली वस्तुओं की एक सूची है।

यह घटनाओं की एक सूची है, Event.objects.all()। कुछ ईवेंट ऑब्जेक्ट्स की रेटिंग होती है, कुछ नहीं करते हैं।

आपको अपने दृश्य में घटनाओं की सूची मिलती है। आप अपने टेम्पलेट में वैकल्पिक संबंधों को संभालते हैं।

{% for e in event_list %} 
    {{ e }} 
    {% if e.rating_set.all %}{{ e.rating_set }}{% endif %} 
{% endfor %} 

एक कूद-बंद बिंदु है।

+0

रेटिंग_सेट वह प्रबंधक है जो रेटिंग के संबंधों का प्रबंधन करता है, इसलिए यह हमेशा मौजूद रहेगा। यहां तक ​​कि यदि आपने एक .count या .all जोड़ दिया है, तो यह आपको वर्तमान रेटिंग के लिए न केवल सभी रेटिंग के लिए विवरण देगा। –

+0

यह मेरा प्रश्न नहीं है :-) e.rating_set एक django.db.models.fields.related.RelatedManager होगा, इसलिए {% अगर e.rating_set%} हमेशा पास होगा। इसे पुन: प्रयास करने का प्रयास करने से आपको TypeError मिल जाएगा: 'relatedManager' ऑब्जेक्ट पुनरावर्तनीय नहीं है।अपना इच्छित व्यवहार प्राप्त करने के लिए आपको e.rating_set.all का उपयोग करना होगा। –

4

एसएलॉट के सुझाव के अलावा, आप डेटाबेस क्वेरी की संख्या को सीमित करने के लिए select_related() का उपयोग करने पर विचार कर सकते हैं; अन्यथा आपका टेम्पलेट लूप के माध्यम से प्रत्येक ईवेंट के पास पर एक प्रश्न करेगा।

Event.objects.all().select_related(depth=1) 

गहराई पैरामीटर की आवश्यकता नहीं है, लेकिन यदि आपके अन्य मॉडल में अतिरिक्त विदेशी कुंजी हैं तो यह जुड़ने की संख्या को सीमित कर देगी।

0

मुझे लगता है कि आप कुछ इस तरह से करना है।

events=Event.objects.filter(rating__user=request.user.id) 
ratings='(select rating from ratings where user_id=%d and event_id=event_events.id '%request.user.id 
events=events.extra(select={'rating':ratings}) 
संबंधित मुद्दे