2009-10-23 21 views
5

Mam prosty schemat muzyczny: Artist, Release, Track i Song. Pierwsze trzy są logicznymi konstrukcjami, a czwarte (Song) jest konkretnym przykładem (Artist, Release, Track) jako mp3, wav, ogg, cokolwiek.Django ORM - select_related and order_by with foreign keys

Mam problem z wygenerowaniem uporządkowanej listy utworów w bazie danych. Połów jest, że zarówno Track i Release mają Artist. Podczas gdy Song.Track.Artist jest zawsze nazwą wykonawcy, Song.Track.Release.Artist może być nazwą wykonawcy lub "Różni wykonawcy" dla kompilacji. Chcę móc sortować według jednego lub drugiego i nie mogę znaleźć prawidłowego sposobu, aby to działało.

Oto mój schemat:

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) 

Moje zapytanie powinno być dość proste; filtrowanie wszystkich utworów należących do określonego użytkownika, a następnie sortowanie ich według Song.Track.Artist.name lub Song.Track.Release.Artist.name. Tu jest mój kodu wewnątrz widoku, który jest sortowanie przez 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') 

nie mogę order_by do pracy, chyba że używam tblname.colname. Przyjrzałem się metodzie obiektu zapytania as_sql, która wskazuje, że gdy połączenie wewnętrzne zostanie utworzone w celu uzyskania Song.Track.Release.Artist, tymczasowa nazwa T6 jest używana dla tabeli Artist, ponieważ wewnętrzne połączenie zostało już wykonane na tej samej tabeli, aby uzyskać 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,)) 

Kiedy umieściłem to jako nazwę tabeli w order_by, to działa (patrz przykładowy wynik powyżej), ale wydaje się to całkowicie nieprzenośne. Z pewnością jest lepszy sposób na zrobienie tego! czego mi brakuje?

Odpowiedz

24

Obawiam się, że naprawdę nie mogę zrozumieć, jakie jest twoje pytanie.

Kilka poprawek: select_related nie ma nic wspólnego z zamawianiem (w ogóle nie zmienia zestawu zapytań, tylko śledzi sprzężenia, aby uzyskać powiązane obiekty i je buforować); i na zamówienie przez pole w pokrewnym modelu używasz notacji podwójnej podkreślenia, nie kropkowanej. Na przykład:

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

Ale w swoim przykładzie, należy użyć „player_artist”, które nie wydają się być polem gdziekolwiek w modelu. I nie rozumiem twojego odniesienia do przenośności.

Powiązane problemy