我有一个简单的分层模型,3只乌龟高。我们说艺术家,专辑,歌曲。在我的视图中过滤生成树的有效方法是什么?
要让艺术家/专辑/歌曲树传递到我的模板,使用任意条件进行过滤,我现在正在执行以下操作:
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的优化从彩虹的另一边提供一些神奇的缓存之外,必须有一种更有效的方法,而不是一直查询每个级别的叶子。
也许创造一棵完整的树(例如每个艺术家和专辑,不检查树叶),然后修剪无叶树枝?或者我应该看{{3}}?
对于额外的积分,一些实际的测试/基准/报告将是受欢迎的。丹科!
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 :(得分:1)
我最终得到了以下内容:
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')左右,但每个乌龟有一个额外的查询。