2017-02-15 36 views
-1

我有一個簡單的分層模型,3龜高。比方說藝術家,專輯,歌曲。在我看來,過濾結果樹的有效方法是什麼?在Django中篩選分層結構的有效方法?

爲了得到一個藝術家/專輯/歌曲樹傳遞給我的模板,用任意條件過濾,目前,我正在做這樣的事情:

for current_artist in Artist.objects.filter(album__song__genre='funkadelic mariachi').distinct(): 
    yield current_artist 

    for current_album in Album.objects.filter(song__genre='funkadelic mariachi').distinct(): 
     yield current_album 

     for current_song in Song.objects.filter(genre='funkadelic mariachi'): 
      yield current_song 

     yield 'End of album' 
    yield 'End of artist' 

但我敢肯定,必須有一個比查詢每個級別的葉子更有效率,除非distinct()和Django的優化提供了來自彩虹另一端的魔法緩存。也許創建一棵樹(例如,每個藝術家和專輯,不檢查樹葉),然後修剪無葉的樹枝?或者我應該看看select_related()

對於額外的分數,一些實際的測試/基準/報告將受到歡迎。丹科!

P.S:我知道django-mptt的善良,但這對它來說太過分了。

詳細的模型並不重要,因爲我正在尋找一個通用的解決方案,但它可能是這樣的:

class Artist: 
    name = models.CharField(max_length=200) 

class Album: 
    name = models.CharField(max_length=200) 
    artist = models.ForeignKey(Artist, on_delete=models.CASCADE) 

class Song: 
    name = models.CharField(max_length=200) 
    album= models.ForeignKey(Album, on_delete=models.CASCADE) 
    genre = models.CharField(max_length=200) 
+0

與某些任意過濾器匹配的所有歌曲的「藝術家專輯歌曲」樹(我不僅僅是funkadelic mariachis;)。 – Chema

+0

該模型由三個類別藝術家,專輯和歌曲組成。我想,他們的任意禮節是無關緊要的。我正在尋找一個簡單的通用解決方案。 – Chema

回答

0

我結束了以下內容:

filters = { "genre": 'funkadelic mariachi' } 
artist = None 
album = None 
result = [] 

# select_related() fetches our chosen songs, and their albums and artists, in a single query 
for song in Song.objects.select_related(
     'album__artist').filter(**filters): 

    if album != song.album and album != None: 
     result.append('End of Album') 

    if artist != song.album.artist: 
     if artist != None: 
      result.append('End of Artist') 
     artist = song.album.artist 
     result.append(artist) 

    if album != song.album: 
     album = song.album 
     result.append(album) 

    result.append(song) 

if result: 
    result.append('End of Album') 
    result.append('End of Artist') 

不非常漂亮,但效率更高。也許prefetch_related()會允許保留三個循環,使用Prefetch('artist',to_attr ='filtered_artists')左右,但是每個龜有一個額外的查詢。