从m2m字段指向self的一个对象获取对象列表

时间:2017-09-28 23:52:05

标签: django postgresql django-orm

我有Business模型,m2m字段保存分支。有些企业有分支,有些企业没有。

class Business(models.Model):
    order = models.IntegerField()
    branches = models.ManyToManyField('self')

我想获得有序(由order字段)业务的列表,其中只有一个(顶级)分支来自链(如果业务有分支)。

例如,让第一个字母表示属于链,而数字表示排序顺序:

AA-0
AB-1
AC-2
AD-3
B-4
C-5
D-6
E-7
FA-8
FB-9
FC-10

A...F...个对象有分支,BCED没有分支。

我想要的清单是:

AA, B, C, D, E, FA

换句话说,除了一个分支外,我想从最终列表中排除任何业务的所有分支。我需要在列表中存在业务,但没有分支。

我是如何用双循环完成的:

object_list = Business.objects.all().order_by('order')
object_list_no_branches = []
for obj in object_list:
    found = False
    for obj_inner in object_list_no_branches:
        found = obj_inner.branches.filter(pk=obj.pk).exists()
        if found:
            break
    if not found:
        object_list_no_branches.append(obj)

但显然循环不是我需要的技术。

是否可以使用Django ORM或PostgreSQL?

2 个答案:

答案 0 :(得分:0)

如果不建议使用图书馆,这不是一件容易的事。你在谈论递归,这在编程中是一个棘手的任务,特别是如果你太深了。尽管如此,您可以使用django-mptt深入了解这个级别。文档解释得非常好,找到了here。这很容易实现。

答案 1 :(得分:0)

好吧,我认为你应该把这种表示信息放在你的模型中。

class Business(models.Model):
    order = models.IntegerField()
    chain_id = models.CharFieldField(max_length = '1') 
    chain_second_letter = models.CharFieldField(max_length = '1')
    branches = models.ManyToManyField('self')
    def representation:
        return '%s%s-%s' % (chain_id,chain_second_letter,order)

然后,给定一个业务对象,您可以这样做以获取有关每个首字母的最小值的信息:

from django.db.models import Min
l = Business.branches.all().values('chain_id').annotate(Min('order')):
## this returns something like 
##[{'chain_id':'A',order__min:'1'},
##{'chain_id':'B',order__min:'0'},etc...]

查找文件所需的输出:

final = []
for obj in l:
   business = Business.objects.get(chain_id = obj['chain_id'],order = obj['order_min'])

   final.append('%s%s' % (business.chain_id,business.chain_second_letter))  

如果您有很多业务需要通过,那么最后一个循环非常缓慢。 Ceirtainlly有更聪明的方法来做到这一点。