Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/django/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
非对称多对多对同模型上的Django递归查询_Django_Django Models_Many To Many - Fatal编程技术网

非对称多对多对同模型上的Django递归查询

非对称多对多对同模型上的Django递归查询,django,django-models,many-to-many,Django,Django Models,Many To Many,我为公司提供服务(在服务和公司之间的多对多)。为了构造我的服务,我使用Django的多对多字段使用树状结构。因此,一个服务可以包含多个其他服务 问题是:如何检索公司拥有的所有服务?使用company.services,我只获得与该公司直接相关的服务。我需要直接相关的服务+包含的服务(以递归方式) 我认为使用Django的ORM框架或编写一条简单的原始SQL语句都无法做到这一点。您可能想看看这样的第三方库,它使您能够更高效地存储/检索以树状结构表示的模型 但是,如果您想通过Python实现这一点,

我为公司提供服务(在
服务
公司
之间的多对多)。为了构造我的服务,我使用Django的多对多字段使用树状结构。因此,一个服务可以包含多个其他服务

问题是:如何检索公司拥有的所有服务?使用
company.services
,我只获得与该公司直接相关的服务。我需要直接相关的服务+包含的服务(以递归方式)


我认为使用Django的ORM框架或编写一条简单的原始
SQL
语句都无法做到这一点。您可能想看看这样的第三方库,它使您能够更高效地存储/检索以树状结构表示的模型

但是,如果您想通过Python实现这一点,您可以这样做:

def get_services(company):
    services = list(company.services.all())
    result = []
    while services:
        service = services.pop(0)
        result.append(service)
        services.extend(list(service.included_services.all()))
    return result

上面的想法非常类似于在树中执行操作。

我认为使用Django的ORM框架或编写简单的原始
SQL
语句无法做到这一点。您可能想看看这样的第三方库,它使您能够更高效地存储/检索以树状结构表示的模型

但是,如果您想通过Python实现这一点,您可以这样做:

def get_services(company):
    services = list(company.services.all())
    result = []
    while services:
        service = services.pop(0)
        result.append(service)
        services.extend(list(service.included_services.all()))
    return result

上面的想法非常类似于在树中执行查询。

我忘了提到我需要一个查询集作为返回值,所以我稍微修改了@ozgur的优秀答案。以防有人也需要:

def get_services(company):
    services = list(company.services.all())
    pks = []
    while services:
        service = services.pop(0)
        if service.pk not in pks:
            pks.append(service.pk)
            services.extend(list(service.included_services.all()))
    return Service.objects.filter(pk__in=pks)

编辑:我还添加了一个潜在循环的检查。

我忘了提到我需要一个QuerySet作为返回值,所以我稍微修改了@ozgur的优秀答案。以防有人也需要:

def get_services(company):
    services = list(company.services.all())
    pks = []
    while services:
        service = services.pop(0)
        if service.pk not in pks:
            pks.append(service.pk)
            services.extend(list(service.included_services.all()))
    return Service.objects.filter(pk__in=pks)

编辑:我还添加了一个潜在循环的检查。

这很好,非常感谢!我有一个递归解决方案,但这种广度优先搜索是一种更具可读性的方法。使用这种方法,您需要小心,不要在服务图中引入任何循环,否则这将在无限循环中运行。这很好,非常感谢!我有一个递归解决方案,但这种广度优先的搜索方法更具可读性。使用这种方法时,您需要小心,不要在服务图中引入任何循环,否则这将在无限循环中运行。