2017-02-15 88 views
-1

私は単純な階層モデルを持っています。 Artist、Album、Songと言ってみましょう。私の見解では、結果のツリーをフィルタリングする効率的な方法は何でしょうか?任意の条件で濾過私のテンプレートに渡すアーティスト/アルバム/ソングツリーを取得するには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の最適化が虹の向こう側からいくつかの魔法のキャッシュを提供していない限り、すべてのレベルで葉までのすべての方法を照会するよりはるかに効率的な方法です。

おそらく木全体を作成する(vg.すべてのアーティストとアルバム、葉をチェックしないで)、そして葉のない枝を刈る?または、私は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

モデルは、アーティスト、アルバム、ソングの3つのクラスで構成されています。彼らの任意の所有権は無関係であると私は思う。私は単純な一般的な解決策を探しています。 – 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')などを使用して3つのループを保持することができますが、1つのタートルにつき1つの追加クエリを使用します。

関連する問題