# связующая таблица топики задачи
tasks_topics= db.Table('tasks_topics',
                       db.Column('task_id', db.Integer, db.ForeignKey('tasks.id')),
                       db.Column('topics_id', db.Integer, db.ForeignKey('topics.id'))
                       )



class Tasks(db.Model):
    __tablename__ = 'tasks'
    __searchable__ = ['task','id']  # these fields will be indexed by whoosh

    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    url = db.Column(db.String(120), comment="ЧПУ задачи в адресе (транслитом)")
    task = db.Column(db.Text, comment='Условие задачи')
    answer = db.Column(db.Text, comment='Ответ')
    status = db.Column(db.Boolean, default=0, comment='Статус: опубликована/неактивна (по умолчанию нет)')
    created_t = db.Column(db.DateTime, comment='Дата и время создания')
    level = db.Column(db.SmallInteger, default=1, comment='Уровень сложности: 1,2 ... (по умолчанию 1 уровень)')

    # связи
    topics = db.relationship('Topics',
                            secondary=tasks_topics,
                            back_populates="tasks")

class Topics(db.Model):
    __tablename__ = 'topics'
    __searchable__ = ['name']

    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    name = db.Column(db.String(140), comment="Уникальное название темы(подтемы)")
    parent = db.Column(db.Integer, default=0, comment="ID родительской темы(если есть)")

    # связи
    tasks = db.relationship('Tasks',
                            secondary=tasks_topics,
                            back_populates="topics")

        # Определение рекурсивного CTE
        topic_parent = db.session.query(
            Topics.id.label('id'),
            func.array([Topics.id]).label('path')
        ).filter(Topics.parent == 0).cte(recursive=True)

        topic_parent_alias = topic_parent.alias()
        topic_parent = topic_parent.union_all(
            db.session.query(
                Topics.id,
                topic_parent_alias.c.path.concat(Topics.id)
            ).join(
                topic_parent_alias,
                topic_parent_alias.c.id == Topics.parent
            )
        )

        # Определение запроса limited_tasks
        limited_tasks = db.session.query(Tasks).order_by(Tasks.id).limit(30).subquery()

        # Основной запрос
        result = db.session.query(
            limited_tasks.c.id,
            limited_tasks.c.task,
            limited_tasks.c.answer,
            func.array_agg(Topics.name.distinct()).label('topic_name')
        ).join(tasks_topics, limited_tasks.c.id == tasks_topics.c.task_id). \
          join(
            topic_parent,
            topic_parent.c.id == tasks_topics.c.topics_id
        ). \
            join(Topics, Topics.id == topic_parent.c.id). \
            group_by(limited_tasks.c.id, limited_tasks.c.task, limited_tasks.c.answer). \
            order_by(limited_tasks.c.id.asc())

        # Использование результатов запроса
        for row in result:
            print(row)

sqlalchemy.exc.ProgrammingError: (psycopg2.ProgrammingError) can't adapt type 'InstrumentedAttribute'
[SQL: WITH RECURSIVE anon_2(id, path) AS
(SELECT topics.id AS id, array(%(array_1)s) AS path
FROM topics
WHERE topics.parent = %(parent_1)s UNION ALL SELECT topics.id AS topics_id, anon_4.path || topics.id AS anon_3       
FROM topics JOIN anon_2 AS anon_4 ON anon_4.id = topics.parent)
 SELECT anon_1.id AS anon_1_id, anon_1.task AS anon_1_task, anon_1.answer AS anon_1_answer, array_agg(DISTINCT topics.name) AS topic_name
FROM (SELECT tasks.id AS id, tasks.url AS url, tasks.task AS task, tasks.answer AS answer, tasks.status AS status, tasks.created_t AS created_t, tasks.level AS level, tasks.users_id AS users_id
FROM tasks ORDER BY tasks.id
 LIMIT %(param_1)s) AS anon_1 JOIN tasks_topics ON anon_1.id = tasks_topics.task_id JOIN anon_2 ON anon_2.id = tasks_topics.topics_id JOIN topics ON topics.id = anon_2.id GROUP BY anon_1.id, anon_1.task, anon_1.answer ORDER BY anon_1.id ASC]
[parameters: {'param_1': 30, 'array_1': [<sqlalchemy.orm.attributes.InstrumentedAttribute object at 0x000001CC5E633A90>], 'parent_1': 0}]
(Background on this error at: http://sqlalche.me/e/14/f405)