6

アーティスト、リリース、トラック、ソングという単純な音楽スキーマがあります。最初の 3 つはすべて論理構造であり、4 番目 (Song) は mp3、wav、ogg などの特定の (アーティスト、リリース、トラック) インスタンスです。

データベース内の曲の順序付きリストを生成するのに問題があります。問題は、 と の両方Trackに. whileは常にパフォーマー名ですが、コンピレーションの場合はパフォーマー名または「Various Artists」のいずれかになります。どちらかでソートできるようにしたいのですが、これを機能させる正しい方法がわかりません。ReleaseArtistSong.Track.ArtistSong.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に使用されることを示しています:ArtistSong.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と機能しますが (上記の出力例を参照)、これは完全に移植性がないようです。確かにこれを行うより良い方法があります! 私は何が欠けていますか?

4

1 に答える 1

26

残念ながら、あなたの質問が何を意味するのか本当に理解できません。

いくつかの修正:select_related順序付けとは関係ありません (クエリセットはまったく変更されません。結合に従って関連オブジェクトを取得し、それらをキャッシュするだけです)。関連モデルのフィールドで並べ替えるには、ドットではなく、2 つのアンダースコア表記を使用します。例えば:

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

しかし、あなたの例では、モデルのどこにもフィールドがないように見える「player_artist」を使用しています。また、移植性への言及がわかりません。

于 2009-10-23T10:07:03.490 に答える