Django-如何过滤多个多对多关系层 [英] Django - how to filter though multiple manyTomany relationship layers
问题描述
请考虑以下设置:
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对象.这是我想要有效实现的目标:
Now, given the pk of a ModelA Object, I want to get and filter all the related ModelC Objects. Here is what i'm trying to achieve efficiently:
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")
)
显然那是行不通的.我目前正在做这样的丑陋事情:
Obviously that doesn't work. I am currently doing something ugly like this:
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")
)
我如何实现我的尝试?
推荐答案
您要获取 ModelC
对象,因此需要在 ModelC
上启动查询.但是,如果您在模型中命名反向关系也可以有所帮助,这样可以更容易地沿相反的方向进行遍历:
You want to get ModelC
objects, so you need to start your query on ModelC
. But it would also help if you name the reverse relationships in your models so that it's easier to traverse in the opposite direction:
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))
modelC_objects = ModelC.objects.filter(parents__modelAs__in=modelA_qs)
第一个 parents
指代 ModelC
对象的父代 ModelB
对象,然后 modelAs
获取每个对象的 ModelA
对象.您可能应该在末尾添加 distinct()
子句,因为您很可能会得到重复的 modelC
对象.
The first parents
refers to the ModelB
objects that are parents to a ModelC
object, then modelAs
fetches the ModelA
objects for each of them. You probably should add a distinct()
clause at the end, because you'll very likely get duplicate modelC
objects.
这篇关于Django-如何过滤多个多对多关系层的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!