在';通过';Django中的递归多目标关系模型

在';通过';Django中的递归多目标关系模型,django,recursion,many-to-many,sql-order-by,Django,Recursion,Many To Many,Sql Order By,假设以下模型: class Category(models.Model): related = models.ManyToManyField('self', symmetrical = False, through = 'CategoryRelation', null = True, blank = True) 假设以下中间“通过”关系: class CategoryRelation(models.Model): source = models.ForeignKey('Cate

假设以下模型:

class Category(models.Model):
    related = models.ManyToManyField('self', symmetrical = False, through = 'CategoryRelation', null = True, blank = True)
假设以下中间“通过”关系:

class CategoryRelation(models.Model):
    source = models.ForeignKey('Category', null = False, blank = False, verbose_name = _('source'), related_name = 'relation_source')

    target = models.ForeignKey('Category', null = False, blank = False, verbose_name = _('target'), related_name = 'relation_target')

    order = models.PositiveIntegerField(_('order'), null = False, blank = True, default = 0)

    class Meta:
        ordering = ( 'order', )
如何在保持顺序的同时获取与给定类别相关的类别对象?以下代码将生成正确的类别对象,但顺序不正确,即使使用
.distinct()
,也会在查询集中包含重复的条目:


以下内容适用于正确订购,但不会遗漏重复条目:

relations = CategoryRelation.objects.filter(source = self)

Category.objects.filter(relation_target__in = relations).order_by('relation_target')
调用.distinct()不会有什么区别,因为.order_by()逻辑是在之后应用的。但是,在本例中,可以利用order是正整数字段的事实,使用Relationship_target字段的order字段的Min值注释每个类别,并使用此新注释字段进行排序:

return Category.objects.filter(relation_target__in = relations).annotate(relation_target_order = models.Min('relation_target__order')).order_by('relation_target_order')
这几乎完成了,但由于此查询的语义本质上使其唯一,因此最好调用.distinct(),以确保distinct标志为True,以便以后可以与其他不同的查询进行组合:

return Category.objects.filter(relation_target__in = relations).annotate(relation_target_order = models.Min('relation_target__order')).order_by('relation_target_order').distinct()
在本例中,.distinct()丝毫不会影响查询,但会确保db/models/sql/query.py method combine(self、rhs、connector)传递其断言:

assert self.distinct == rhs.distinct, \ ...

以下内容适用于正确订购,但不会遗漏重复条目:

relations = CategoryRelation.objects.filter(source = self)

Category.objects.filter(relation_target__in = relations).order_by('relation_target')
调用.distinct()不会有什么区别,因为.order_by()逻辑是在之后应用的。但是,在本例中,可以利用order是正整数字段的事实,使用Relationship_target字段的order字段的Min值注释每个类别,并使用此新注释字段进行排序:

return Category.objects.filter(relation_target__in = relations).annotate(relation_target_order = models.Min('relation_target__order')).order_by('relation_target_order')
这几乎完成了,但由于此查询的语义本质上使其唯一,因此最好调用.distinct(),以确保distinct标志为True,以便以后可以与其他不同的查询进行组合:

return Category.objects.filter(relation_target__in = relations).annotate(relation_target_order = models.Min('relation_target__order')).order_by('relation_target_order').distinct()
在本例中,.distinct()丝毫不会影响查询,但会确保db/models/sql/query.py method combine(self、rhs、connector)传递其断言:

assert self.distinct == rhs.distinct, \ ...