Реализовать рекурсивную функцию для проверки наличия или отсутствия дочерних моделей

Я пытаюсь реализовать рекурсивную функцию, которая будет проверять, есть ли у объекта ребенок с идентификатором родителя. Если имеет, то добавляет его в список и рекурсивно вызывает функцию, чтобы проверить, есть ли у вновь добавленного ребенка другие дети.

Мой текущий код, который работает нормально, как и ожидалось:

    def get_nav_items(self, instance):
        
        childs = []
        items = Content.objects.filter(parent_id=instance)

        for item in items:
            childs.append(item)

        for item in items:
            ch = Content.objects.filter(parent_id=item)
            if ch.count() > 0:
                for c in ch:
                    childs.append(c)
        menu_objecs = []
        for item in childs:
            menu_objecs.append(ContentNevItemSerializer(item).data)
            
        return menu_objecs

Метод, который сейчас не возвращает никакого результата:

    def extract_item(self, nav_obj, nav_list = []):
        cont = Content.objects.filter(parent_id=nav_obj)

        if len(cont) == 0:
            return nav_list
        
        else:
            for ct in cont:
                self.extract_item(ct, nav_list)
            # nav_list.append(cont)
            return nav_list

Здесь представлена рекурсивная версия проверки дочерних объектов запросов django.

Трюк заключался в том, чтобы передать через параметр balnk список и проверить, есть ли в кверисете объект больше нуля. Если результат равен нулю, то вернуть выполнение, вернув переданный список.

Однако, если есть объект, то он будет добавлять каждый объект в список и рекурсивно вызывать функцию и, наконец, возвращать полный список.

N.B: Проверка объекта с помощью len() приведет к тому, что quryset будет повторно проверять базу данных. Вместо этого, поскольку django кэширует результат ORM, поэтому count() будет использовать кэш и вычислять уже полученный результат.

    def extract_item(self, nav_obj, nav_list: list):
        """
        Recursively call and check if there is any child available.
        """
        cont = Content.objects.filter(parent_id=nav_obj)
        if len(cont) == 0:
            return nav_list
        else:
            for ct in cont:
                nav_list.append(ct)
                self.extract_item(ct, nav_list)
            return nav_list

    def get_nav_items(self, instance):
        """
        Get all the children for the model object
        """
        childs = self.extract_item(instance, [])
        menu_objecs = []
        for item in childs:
            menu_objecs.append(ContentNevItemSerializer(item).data)
        return menu_objecs
Вернуться на верх