У меня есть простая музыкальная схема: Artist, Release, Track и Song. Первые 3 являются логическими конструкциями, в то время как четвертый (Song) является конкретным экземпляром (Artist, Release, Track) в виде mp3, wav, ogg и т. Д.
У меня возникли проблемы при создании упорядоченного списка песен в базе данных. Уловка в том, что и 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
, оно работает (см. Пример выходных данных выше), но это кажется совершенно непереносимым. Конечно, есть лучший способ сделать это! Чего мне не хватает?