我有一個簡單的音樂模式:Artist,Release,Track和Song。前三個都是邏輯構造,而第四個(歌曲)是一個(藝術家,發佈,音軌)的特定實例,如mp3,wav,ogg等等。Django ORM - 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
對它們進行排序。這裏是我的代碼視圖,它是由Song.Track.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
。我查看了底層查詢對象的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
中的表名時,它確實有效(請參閱上面的示例輸出),但這看起來完全不可移植。當然有更好的方法來做到這一點!我錯過了什麼?