如何构建django-mptt查询加入mptt层次结构元素的任何后代?

时间:2014-09-10 15:59:38

标签: django django-mptt

我想用django-mptt构建蔬菜类的层次结构(Fruit - > Berries - > Strawberry - > Douglas Strawberry)是该品种的最后一个层次。零售商的库存通常与叶片水平,品种(金苹果,道格拉斯草莓......)有关,但消费者习惯于询问上层(Apple,Pear,Orange,Lettuce ......)。所以一个有用的查询将是“选择所有零售商都有'草莓'或任何孩子的库存产品。

让我用一些示例代码来说明它:

class Vegetable(MPTTModel) :
    name = TextField(...)
    group = TreeForeignKey('self',
        related_name='subgroups',
        null=True, default=None)
    class MPTTMeta:
        parent_attr = 'group'

    def getRetailers(self) :
        # Here the missing code

class Retailer(Model) :
    name = TextField(...)
    vegetables = ManyToMany(Vegetable, null=True)

fruits = Vegetable(name='Fruit')
pears = Vegetable(name='Pear', group=fruits)
apples = Vegetable(name='Apple', group=fruits)
goldenApples = Vegetable(name='Golden Apple', group=apples)
royalApples = Vegetable(name='Royal Apple', group=apples)
for o in fruits, pears, apples, goldenApples, royalApples : o.save()

toni = Retailer(name='Toni')
pere = Retailer(name='Pere')
benet = Retailer(name='Benet')
mall = Retailer(name='CityMall')
for o in toni, pere, benet, mall : o.save()

toni.vegetables.add(pears)
pere.vegetables.add(goldenApple)
pere.vegetables.add(royalApple)
benet.vegetables.add(goldenApple)
mall.vegetables.add(apples)

# The following query set should return Pere, Benet and CityMall but not Toni.
Vegetable.get(name='Apple').getRetailers()

那么我应该如何使用Django API构建这样的查询?

1 个答案:

答案 0 :(得分:2)

您可以使用MPTTModel获取所有get_descendants个后代的查询集:

  

创建一个包含此模型实例后代的QuerySet,   按树顺序。

     

如果include_selfTrue,则QuerySet也会包含   这个模型实例。

对于特定的蔬菜:

# get retailers where...
retailers = Retailers.objects.filter(
    # ...one or more of it's vegetables are in the list of
    # all things descendant of 'vegetable', including itself.
    vegetables__in=vegetable.get_descendants(include_self=True)
).distinct()