2013-02-15 57 views
7

मैं Django में ऑब्जेक्ट्स prefetch_related कैसे कर सकता हूं और मध्यस्थ तालिका में किसी फ़ील्ड द्वारा उन्हें ऑर्डर कर सकता हूं?Django: prefetch_related परिणाम मध्यस्थ तालिका के क्षेत्र द्वारा आदेश दिया गया

यहाँ मॉडल के साथ मैं काम कर रहा हूँ है:

class Node(models.Model): 
    name = models.CharField(max_length=255) 
    edges = models.ManyToManyField('self', through='Edge', symmetrical=False) 


class Edge(models.Model): 
    from_node = models.ForeignKey(Node, related_name='from_node') 
    to_node = models.ForeignKey(Node, related_name='to_node') 

    weight = models.FloatField(default=0) 

एक नोड देखते हुए, मैं संबंधित नोड्स के सभी, वजन द्वारा आदेश दिया prefetch करना चाहते हैं।

जब मैं इस क्वेरी का उपयोग करें:

n = Node.objects.prefetch_related('to_node').order_by('edge__weight').get(name='x') 

order_by कोई प्रभाव नहीं है।

संपादित करें:

मेरे सर्वश्रेष्ठ उत्तर अब तक

n = Node.objects.get(name='x') 
edges = Edge.objects.filter(from_node=n).prefetch_related('to_node').order_by('weight') 

तो बजाय n.edges पुनरावृत्ति (मैं पसंद करते हैं) के रूप में की है, मैं edges.to_node

+0

आप एज तालिका पर नोड तालिका पर खंड द्वारा ऑर्डर दे रहे हैं। तो, उल्लिखित परिणाम की उम्मीद है। –

+0

वास्तव में, लेकिन किनारे की मेज पर इसे कैसे रखा जा सकता है? –

उत्तर

4

बस एक वैचारिक विचार (स्मृति से लिखा गया)।

समस्या यह है कि order_by नोड मॉडल को संदर्भित करता है।

  1. जोड़ें 'वजन' क्षेत्र है, जो सामान्य रूप से लोप हो जाएगा:

    हालांकि, वहाँ

    Node.objects.get(name='x').edges.extra(select={'weight':'%s.weight' % Edge._meta.db_table}).order_by('weight') 
    

    इस के लिए एक रास्ता के लिए ORM के लिए बाध्य करेगा है।

  2. इसके परिणाम परिणाम दें।

प्रश्नों की संख्या समान होनी चाहिए जैसे कि prefetch_query काम करता है, एक नोड प्राप्त करने के लिए, दूसरा संबंधित नोड्स प्राप्त करने के लिए।

दुर्भाग्य से यह एक बहुत ही 'साफ' समाधान नहीं है, क्योंकि हमें _meta का उपयोग करने की आवश्यकता है।

+1

साफ नहीं हो सकता है लेकिन मैं पुष्टि कर सकता हूं कि यह काम करता है। धन्यवाद! –

0

नहीं कि हालांकि साफ पुनरावृति ..

//Untested Code 
Node n = Node.objects.get(name="x") 

//This would return To Node IDs' ordered by weight 

n.edges.filter(from_node = n).values_list('to_node', flat=True).order_by('weight') 
5

आजकल, आप भी इस लक्ष्य को हासिल करने के लिए प्रीफ़ेच वर्ग का उपयोग कर सकते हैं:

https://docs.djangoproject.com/en/1.10/ref/models/querysets/#django.db.models.Prefetch

या, यदि आप एक डिफ़ॉल्ट के रूप में यह सब समय क्या करना चाहते हैं, तो आप पर मेटा आदेश पर गौर कर सकते मध्यस्थ तालिका, कुछ:

class SomeThroughModel(models.Model): 
    order = models.IntegerField("Order", default=0, blank=False, null=False) 
    ... 

    class Meta: 
     ordering = ['order'] # order is the field holding the order 

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

  • कोई संबंधित समस्या नहीं^_^