2009-10-23 15 views
5

मेरे पास एक साधारण संगीत स्कीमा है: कलाकार, रिलीज, ट्रैक, और गीत। पहले 3 सभी तार्किक संरचनाएं हैं जबकि चौथा (गीत) एक एमपी 3, वाव, ओग, जो कुछ भी है (कलाकार, रिलीज, ट्रैक) का एक विशिष्ट उदाहरण है।डीजेंगो ओआरएम - विदेशी कुंजी के साथ select_related और order_by

मुझे डेटाबेस में गाने की ऑर्डर की गई सूची उत्पन्न करने में समस्या हो रही है। पकड़ यह है कि Track और Release दोनों में Artist है। जबकि Song.Track.Artist हमेशा कलाकार का नाम होता है, Song.Track.Release.Artist संकलन के लिए या तो कलाकार नाम या "विभिन्न कलाकार" हो सकता है। मैं एक या दूसरे से सॉर्ट करने में सक्षम होना चाहता हूं, और मैं इस काम को करने का सही तरीका नहीं समझ सकता।

यहाँ मेरी स्कीमा है:

class Artist(models.Model): 
    name = models.CharField(max_length=512) 

class Release(models.Model): 
    name = models.CharField(max_length=512) 
    artist = models.ForeignKey(Artist) 

class Track(models.Model): 
    name = models.CharField(max_length=512) 
    track_number = models.IntegerField('Position of the track on its release') 
    length = models.IntegerField('Length of the song in seconds') 
    artist = models.ForeignKey(Artist) 
    release = models.ForeignKey(Release) 

class Song(models.Model): 
    bitrate = models.IntegerField('Bitrate of the song in kbps') 
    location = models.CharField('Permanent storage location of the file', max_length=1024) 
    owner = models.ForeignKey(User) 
    track = models.ForeignKey(Track) 

मेरे प्रश्न काफी सरल होना चाहिए; किसी विशिष्ट उपयोगकर्ता के स्वामित्व वाले सभी गीतों के लिए फ़िल्टर करें, और फिर उन्हें Song.Track.Artist.name या Song.Track.Release.Artist.name द्वारा क्रमबद्ध करें।

songs = Song.objects.filter(owner=request.user).select_related('track__artist', 'track__release', 'track__release__artist').order_by('player_artist.name') 

मैं order_by जब तक कि मैं tblname.colname का उपयोग काम करने के लिए नहीं मिल सकता है: यहाँ एक दृश्य है, जो Song.Track.Artist.name द्वारा छँटाई है अंदर मेरे कोड है। मैंने अंतर्निहित क्वेरी ऑब्जेक्ट की as_sql विधि पर एक नज़र डाली, जो इंगित करता है कि Song.Track.Release.Artist प्राप्त करने के लिए आंतरिक जुड़ने के लिए T6 का उपयोग Artist तालिका के लिए किया जाता है क्योंकि Song.Track.Artist:

प्राप्त करने के लिए एक ही तालिका में आंतरिक प्रवेश पहले से ही किया गया था
>>> songs = Song.objects.filter(owner=request.user).select_related('track__artist', 'track__release', 'track__release__artist').order_by('T6.name') 
>>> print songs.query.as_sql() 
('SELECT "player_song"."id", "player_song"."bitrate", "player_song"."location", 
    "player_song"."owner_id", "player_song"."track_id", "player_track"."id", 
    "player_track"."name", "player_track"."track_number", "player_track"."length", 
    "player_track"."artist_id", "player_track"."release_id", "player_artist"."id", 
    "player_artist"."name", "player_release"."id", "player_release"."name", 
    "player_release"."artist_id", T6."id", T6."name" FROM "player_song" INNER JOIN 
    "player_track" ON ("player_song"."track_id" = "player_track"."id") INNER JOIN 
    "player_artist" ON ("player_track"."artist_id" = "player_artist"."id") INNER JOIN 
    "player_release" ON ("player_track"."release_id" = "player_release"."id") INNER JOIN 
    "player_artist" T6 ON ("player_release"."artist_id" = T6."id") WHERE 
    "player_song"."owner_id" = %s ORDER BY T6.name ASC', (1,)) 

जब मैं order_by में तालिका नाम के रूप में इस डाल यह करता है काम (ऊपर के उदाहरण उत्पादन देखें), लेकिन यह पूरी तरह गैर पोर्टेबल लगता है। निश्चित रूप से ऐसा करने का एक बेहतर तरीका है! मैं क्या खो रहा हूँ?

उत्तर

24

मुझे डर है कि मैं वास्तव में समझ नहीं पा रहा हूं कि आपका प्रश्न क्या है।

कुछ सुधार: select_related के पास आदेश देने के साथ कुछ भी नहीं है (यह क्वेरीसेट को बिल्कुल नहीं बदलता है, बस संबंधित वस्तुओं को प्राप्त करने के लिए जुड़ता है और उन्हें कैश करता है); और किसी संबंधित मॉडल में किसी फ़ील्ड द्वारा ऑर्डर करने के लिए आप डबल-अंडरस्कोर नोटेशन का उपयोग करते हैं, बिंदीदार नहीं। उदाहरण के लिए:

Song.objects.filter(owner=request.user).order_by('track__artist__name') 

लेकिन अपने उदाहरण में, आप 'player_artist' है, जो अपने मॉडल में कहीं भी एक क्षेत्र होने के लिए प्रतीत नहीं होता है का उपयोग करें। और मैं पोर्टेबिलिटी के संदर्भ को समझ नहीं पा रहा हूं।

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