Django多对多查询满足特定条件

时间:2012-02-28 15:35:20

标签: python django many-to-many

我有这两个模型

class Genre( TimeStampAwareModel ):
   genre = models.CharField ( max_length = 255, blank = False )
   parent = models.ForeignKey ( 'self', null=True, blank=True, related_name = "childs" )
   ..
class Track( TimeStampAwareModel ):
   ....
   genre = models.ManyToManyField( Genre )

我有作为流派的输入列表[Pop,Rock,..],因为Pop和Rock也有儿童流派。现在我想过滤满足以下条件的所有曲目

(G1parent OR G1child1或G1child2 OR .....)和(G2parent OR G2child1或G2child2 OR .....)

def get_genre_tracks(list_genre):
   ....
   ...
   return tracks

这里G1parent是Pop,G2parent是Rock,我怎么能得到这个?寻找一个优雅的解决方案。

谢谢!

1 个答案:

答案 0 :(得分:4)

如果我理解正确,您希望所有具有“Rock”类型的曲目都是具有“Rock”作为父级的流派。如果是这样的话:

from django.db.models import Q

Track.objects.filter(Q(genre__genre='Rock') | Q(genre__parent__genre='Rock')).distinct()

修改

实际上,在重新阅读问题之后,似乎你想要我所说的,但是要一起列出一个类型,而不是一次一个。为此,您只需要调整上面的代码,如:

Track.objects.filter(Q(genre__genre__in=['Rock', 'Pop']) | Q(genre__parent__genre__in=['Rock', 'Pop'])).distinct()

<强>更新

啊,那它有点复杂但仍然可行。

has_rock_genres = Q(genre__genre='Rock') | Q(genre__parent__genre='Rock')
has_pop_genres = Q(genre__genre='Pop') | Q(genre__parent__genre='Pop')

Track.objects.filter(has_rock_genres & has_pop_genres).distinct()

你可以在一行中完成所有这些,但是那时代码变得有点混乱。

<强>更新

今天真的给我一个心理锻炼,不是吗? ;)

您需要执行以下操作:

query = None
for genre in genres:
    if query is None:
        query = Q(genre__genre=genre) | Q(genre__parent__genre=genre)
    else:
        query = query & (Q(genre__genre=genre) | Q(genre__parent__genre=genre))

    Track.objects.filter(query).distinct()