Django-如何通过多个manyTomany关系层进行过滤

问题描述 投票:0回答:1

请考虑以下设置:

class ModelA(models.Model):
    foreign = models.ForeignKey(ModelB, on_delete=models.CASCADE)
    children = models.ManyToManyField('self', related_name="parent", symmetrical=False, blank=True)

class ModelB(models.Model):
    caption = models.CharField(db_index=True, max_length=50, null=False, unique=True)
    children = models.ManyToManyField(ModelC, blank=True)

class ModelC(models.Model):
    ...lots of fields

现在,给定ModelA对象的pk,我想获取并过滤所有相关的ModelC对象。这是我想要有效实现的目标:

modelC_objects = ModelA.objects.get(pk=modelA_id).children.foreign.children
    .filter(pk__lte=last_id)      
    .exclude(is_private=True)
    .order_by('-pk')[0:100]
    .prefetch_related("other")
)

显然,这不起作用。我目前正在做这样的丑陋的事情:

modelA_objects = ModelA.objects.get(pk=modelA_id).children
modelC_querysets = [modelA.foreign.children for modelA in modelA_objects]
if modelC_querysets:
    modelC_objects = modelC_querysets[0]
    modelC_querysets.pop(0)
    for x in modelC_querysets:                    
        modelC_objects = modelC_objects | x
filtered = (modelC_objects.filter(pk__lte=last_id)      
   .exclude(is_private=True)
   .order_by('-pk')[0:100]
   .prefetch_related("other")
)

如何实现我的尝试?

django many-to-many django-filter
1个回答
0
投票

您要获取ModelC对象,因此需要在ModelC上开始查询。但是,如果在模型中命名反向关系,也将有所帮助,这样可以更容易地沿相反方向遍历:

class modelA:
    foreign = models.ForeignKey(ModelB, related_name='modelAs' on_delete=models.CASCADE)
    ...

class modelB:
    children = models.ManyToManyField(ModelC, related_name='parents')
    ...

modelA_qs = ModelA.objects.filter(Q(id=pk) | Q(parents__id=pk))
filtered = ModelC.objects.filter(parents__modelAs__in=modelA_qs)

[第一个parents指的是作为ModelB对象的父对象的ModelC对象,然后modelAs为每个对象获取ModelA对象。您可能应该在末尾添加distinct()子句,因为您很可能会获得重复的modelC对象。

© www.soinside.com 2019 - 2024. All rights reserved.