在 Django 中过滤深层嵌套的 related_set

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

有两种型号:

class Subject(Model):
    categories = ManyToManyField(Category, related_name='subjects')

class Category(Model):
    parent = ForeignKey('self', related_name='subcategories')

这应该被翻译成以下剩余输出:

[
    {
        ...,
        "categories": [
            {"subcategories": [{}, {} ... {}]},
            {"subcategories": [{}, {} ... {}]}
        ],
    },
    {
        ...,
        "categories": [
            {"subcategories": [{}, {} ... {}]},
            {"subcategories": [{}, {} ... {}]}
        ],
    }
]

问题是为每个类别设置一组子类别,这些子类别与祖先主题存在多对多关系。

到目前为止,我认为查询集应该是这样的:

Subject.objects.prefetch_related(
    Prefetch(
        lookup="categories",
        queryset=Category.objects.filter(parent__isnull=True)
        .prefetch_related(
            Prefetch(
                lookup="subcategories",
                queryset=Subquery(
                    Category.objects.filter(
                        parent__pk=OuterRef("pk"),
                        subjects__id__in=OuterRef(OuterRef("pk")),
                    )
                )
            )
        )
        .distinct(),
    ),
)

但这给出了错误:

AttributeError: 'Subquery' object has no attribute '_chain'

查询集出了什么问题。正确的做法是什么?

django django-rest-framework django-queryset
1个回答
0
投票

您尝试在单个语句中执行的方式既不简洁也不高效。 更好的方法是使用递归函数,然后安排响应。 你可以看看以下。

def get_sub_categories(category):
    """
    This is a function which we are using recursively to get all subcategories for a catefgory 
    """
    category_data = {'name': category.name}
    subcategories = category.subcategories.all()
    if subcategories:
       category_data['subcategories'] = [get_sub_categories(subcategory) for subcategory in subcategories]

    return category_data

使用上述功能,您可以获得给定主题的所需响应。

subject = Subject.objects.get(id=subject_id)
categories = subject.categories.all()
data = [get_sub_categories(category) for category in categories]

您的数据将如下所示,您可以进一步进行调整以根据您的需要获取所需的字段

[
    {
        "name": "Government Exam",
        "subcategories": [
            {
                "name": "SSC",
                "subcategories": [
                    {
                        "name": "Physical",
                        "subcategories": [
                            {
                                "name": "Body 1"
                            },
                            {
                                "name": "Body 2"
                            }
                        ]
                    },
                    {
                        "name": "Written",
                        "subcategories": [
                            {
                                "name": "Socialogy"
                            },
                            {
                                "name": "Enviromental"
                            }
                        ]
                    }
                ]
            },
            {
                "name": "NDA"
            }
        ]
    }
]
© www.soinside.com 2019 - 2024. All rights reserved.