在Python中获取一行和一行(树函数)

2024-10-03 21:34:18 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在尝试将这个PHP代码转换成Python。它只是返回树层次结构中的选项。在

function getAllSectors(&$output = null, $parent_id = 0, $indent = null){

        $statement = $this->connect()->prepare("SELECT id, name FROM sectors WHERE parent_id =:parent_id ORDER BY parent_id, sort_order");

        $statement->execute(array(
            'parent_id'     => $parent_id
        ));

        // show the sectors one by one
        while($row = $statement->fetch()){
            $output .= '<option value=' . $row['id'] . '>' . $indent . $row['name'] . "</option>";
            if($row['id'] != $parent_id){
                // In case the current sectors's id is different than $parent_id
                // I call the function again with new parameters(so it is recursive)
                $this->getAllSectors($output, $row['id'], $indent . "&nbsp;&nbsp;");
            }
        }
        // return the list of sectors(call out is in index.php)
        return $output;
    }

我在Python中尝试过:

^{pr2}$

我在用Python,SQLAlchemy,Tornado,主干。在

但是我不知道如何通过引用传递output参数。我认为Python版本有无限循环,对吗?谁能给我提些建议吗?在


Tags: thenameidoutputisfunctionthisone
1条回答
网友
1楼 · 发布于 2024-10-03 21:34:18

PHP代码的正确翻译是:

def get_all_categories(cls, parent_id=None, indent=''):
    output = []
    categories = cls.db.query(Category).filter(~Category.is_deleted, Category.parent_id==parent_id)
    for cat in categories.order_by(Category.sort_order):
        output.append(
            '<option value={cat.id}>{indent}{cat.name}</option>\n'.format(
                cat=cat, indent=indent))
        if cat.id != parent_id:
            output.append(cls.get_all_categories(cat.id, indent + '&nbsp;&nbsp;'))
    return ''.join(output)

不需要将output传入递归调用,只需收集输出并将其添加到正在生成的当前输出中。我使用了一个列表来避免重复的字符串连接(这将为您提供二次性能,而不是线性的)。在

您还缺少ORDER BY子句;当您同时对父id进行筛选时,不需要按parent_id排序(它们都将是相同的),因此只需要对sort_order列进行排序。在

我假设这是SQLAlchemy;您可以使用~来声明WHERE NOT <column>子句。在

您还应该考虑将表示与作为树检索类别分开。然后,您可以使用生成器方法,避免将整个树保存在内存中的内存占用(尽管SQLAlchemy无论如何都会缓存大部分内容):

^{pr2}$

然后使用模板引擎递归地呈现children元素。在

对于演示,首先让我们在内存数据库中构建一些类别;这将使用模型的简化版本;树如下所示:

    • 垃圾邮件
    • 火腿
  • 酒吧
    • 消失(标记为已删除)

设置代码:

>>> from sqlalchemy import create_engine
>>> engine = create_engine('sqlite:///:memory:')
>>> from sqlalchemy.ext.declarative import declarative_base
>>> Base = declarative_base()
>>> from sqlalchemy import Column, Integer, String, Boolean, ForeignKey
>>> class Category(Base):
...     __tablename__ = 'category'
...     id = Column(Integer, primary_key=True, autoincrement=True)
...     name = Column(String(50))
...     parent_id = Column(Integer, ForeignKey('category.id'))
...     sort_order = Column(Integer)
...     is_deleted = Column(Boolean, default=False)
...
>>> Base.metadata.create_all(engine)
>>> from sqlalchemy.orm import sessionmaker
>>> session = sessionmaker(bind=engine)()
>>> foo = Category(name='Foo', sort_order=1)
>>> bar = Category(name='Bar', sort_order=2)
>>> session.add_all([foo, bar])
>>> session.flush()
>>> spam = Category(name='Spam', parent_id=foo.id, sort_order=1)
>>> ham = Category(name='Ham', parent_id=foo.id, sort_order=2)
>>> gone = Category(name='Gone', parent_id=bar.id, sort_order=1, is_deleted=True)
>>> session.add_all([spam, ham, gone])
>>> session.commit()

然后使用一个伪类将类方法绑定到,可以生成输出:

>>> class Demo:
...     db = session
...     @classmethod
...     def get_all_categories(cls, parent_id=None, indent=''):
...         output = []
...         categories = cls.db.query(Category).filter(~Category.is_deleted, Category.parent_id==parent_id)
...         for cat in categories.order_by(Category.sort_order):
...             output.append(
...                 '<option value={cat.id}>{indent}{cat.name}</option>\n'.format(
...                     cat=cat, indent=indent))
...             if cat.id != parent_id:
...                 output.append(cls.get_all_categories(cat.id, indent + '&nbsp;&nbsp;'))
...         return ''.join(output)
...
>>> print(Demo.get_all_categories())
<option value=1>Foo</option>
<option value=3>&nbsp;&nbsp;Spam</option>
<option value=4>&nbsp;&nbsp;Ham</option>
<option value=2>Bar</option>

相关问题 更多 >